在线预览地址: https://ihope_top.gitee.io/bamboo-pole/ gitee地址: https://gitee.com/ihope_top/my-demo 吕布回城文章: https://cloud.tencent.com/developer/article/2078692
前言
前两天用css3写了一个吕布的回城特效,感觉还行,不过吕布有了,作为吕布对象的貂蝉怎么能没有呢?今天就来用css3再给貂蝉也来一套,写的不好不要喷我哦
首先还是先来看效果图,确实有点简单哈
【GIF版】
人形立绘为文章发布后加上的,对代码结构进行了细微跳转,可能与文章内部分代码不同,但基本没有大的影响,可以直接点击文章头部链接查看源代码
【代码块版】
由于代码块的显示区域太小,这里对body进行了缩放 https://code.juejin.cn/pen/7089100660683046920
代码实现
这次的地盘部分我们没有采用较为复杂的图形,主要也写不出来,这里就参考了游戏默认的回城效果,两个嵌套的圆环,外加一点内阴影,这样就搞定了。
代码语言:javascript复制<!-- 回城底部圆形波 -->
<div id="bottom-wrap">
<div class="bottom-item">
</div>
</div>
代码语言:javascript复制/* 圆形底纹 */
#bottom-wrap {
position: absolute;
width: 600px;
height: 600px;
left: 50%;
margin-left: -300px;
bottom: -300px;
border-radius: 50%;
transform-style: preserve-3d;
box-sizing: border-box;
transform: rotateX(90deg);
border: 5px solid #ffb9ff;
box-shadow: 0 0 50px 2px rgb(255 155 238 / 80%) inset;
}
.bottom-item {
border: 5px solid #ffb9ff;
box-shadow: 0 0 50px 2px rgb(255 155 238 / 80%) inset;
width: 75%;
height: 75%;
box-sizing: border-box;
border-radius: 50%;
left: 50%;
top: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
下面我们再来加一个回城的光束,不让画面显得那么单调,这个我们直接加到底盘中,利用定位把它立起来就好了,再加一个渐变,透明度之类的就好了。
代码语言:javascript复制<div id="bottom-wrap">
<div class="bottom-item">
<div class="bottom-content">
</div>
</div>
</div>
代码语言:javascript复制.bottom-content {
position: absolute;
width: 100%;
height: 4500px;
opacity: .7;
background-image: linear-gradient(to right, transparent, rgb(255 151 247 / 60%) ,rgb(253 192 255), rgb(255 151 247 / 60%) 80%, transparent);
mask-image: linear-gradient(to bottom, transparent -10%,#fff 20%, #fff 80%, transparent);
-webkit-mask-image: linear-gradient(to bottom, transparent -10%,#fff 20%, #fff 80%, transparent);
bottom: 50%;
}
现在画面就变成了这个样子
然后我们再来加一点动态的效果,给一个向上运动的圆环,我们可以直接把里面的那个圆复制一个,然后给一个不断向上运动的动画
代码语言:javascript复制 <!-- 回城底部圆形波 -->
<div id="bottom-wrap">
<div class="bottom-item">
<div class="bottom-content">
</div>
</div>
<div class="bottom-item copy"></div>
</div>
代码语言:javascript复制.bottom-item.copy {
animation: moveTop .5s linear infinite;
}
@keyframes moveTop {
from{
opacity: 1;
transform: translate(-50%, -50%) translateZ(0);
} to{
opacity: 0;
transform: translate(-50%, -50%) translateZ(1200px);
}
}
这样子就有点像那么回事了
我们在上一篇中用到的旋转的光束效果挺不错的,这里也可以拿过来,改改颜色,再变换个角度,直接就能用,具体咋实现的可以参考上篇文章,文章头部也有上一篇的链接。
代码语言:javascript复制 <!-- 旋转光圈 -->
<div class="light-wrap one">
<div class="light-item one"></div>
</div>
<div class="light-wrap two">
<div class="light-item two"></div>
</div>
代码语言:javascript复制.light-wrap {
position: absolute;
width: 800px;
height: 800px;
left: 50%;
bottom: -400px;
margin-left: -400px;
transform-style: preserve-3d;
transform: rotateX(0deg) rotateZ(30deg);
margin-bottom: 375px;
}
.light-wrap.one {
transform: rotateX(0deg) rotateZ(150deg);
}
.light-item {
width: 800px;
height: 800px;
border-radius: 50%;
box-sizing: border-box;
border: 10px solid #ffb9ff;
/* box-shadow: 0 0 3px 1px rgb(255 246 82) inset; */
mask-image: linear-gradient(to top, transparent 25%, #000 75%);
-webkit-mask-image: linear-gradient(to top, transparent 25%, #000 75%);
clip-path:polygon(0% 25%, 50% 50%, 0% 75%);
-webkit-clip-path:polygon(0% 25%, 50% 50%, 0% 75%);
}
.light-item.one {
animation: rotate-light 3s linear infinite;
}
.light-item.two {
/* margin-bottom: 450px; */
animation: rotate-light 3s linear infinite;
}
@keyframes rotate-light {
from{
transform: rotateY(360deg) rotateX(90deg);
} to{
transform: rotateY(0deg) rotateX(90deg);
}
}
基础回城部分到这里就已经完成了,但是这样未免太简单了点,所以我们再来给他加一点花瓣飘落的效果,如果有看过我写的关于下雪的那篇文章的话,应该会发现,花瓣飘落和下雪的样子差不多,所以那里的代码我们可以直接复用,当然,这里也会再讲解一遍。
首先就是来画一个花瓣,这里我们利用圆角画出花瓣的形状,再利用渐变和阴影给花瓣加上颜色和发光效果
因为这里我们需要让花瓣斜着飘下来,营造出有风的感觉,所以肯定不能直上直下的,所以再给它来一点倾斜的角度transform: rotateZ(30deg)
,飘着的时候肯定不只是水平方向会倾斜,它的自身也有会有旋转,这里我们再来给他一个旋转的动画,注意,管理3d视角的我们都需要加上transform-style: preserve-3d;
,然后效果如下
是不是有那么点感觉了,当然立体的花瓣我是画不出来的啊,所以看上去上一个纸片一样,不过不注意看的话倒也看的过去,之后我们就来用js生成花瓣,关于生成花瓣的细节我全都写在了下面的js代码中并做了详细的注释
代码语言:javascript复制.flower-item {
position: absolute;
width: 15px;
height: 20px;
background-image: radial-gradient(#fdedff 40%, #ffb9ff);
box-shadow: 0 5px 10px 2px rgba(255, 255, 255, .8);
border-radius: 80% 80% 100% 100%;
transform-style: preserve-3d;
transform: rotateZ(30deg);
animation: rotate-flower 5s linear infinite;
}
@keyframes rotate-flower {
from{
transform: rotateZ(30deg) rotateY(0deg);
} to{
transform: rotateZ(30deg) rotateY(360deg);
}
}
代码语言:javascript复制/*
* @Author: 贺永胜
* @Date: 2022-04-14 22:55:03
* @公众号: 百里青山
* @LastEditors: 贺永胜
* @LastEditTime: 2022-04-23 00:45:42
* @Descripttion:
*/
// 花朵飘落
let lastflowerTime = 0, // 上次生成花瓣的时间
flowerFrequency = 1, // 生成花瓣的频率
screenWidth = document.documentElement.clientWidth, // 屏幕宽度
screenHeight = document.documentElement.clientHeight, // 屏幕高度
flowerAngle = 60, // 花瓣偏移角度
flowerSpeed = 3, // 花瓣移动速度
createflowerInterval = null // 花瓣生成的定时器
function flowerStart () {
console.log(444);
// 花瓣生成的频率
let now = new Date().getTime()
if (now - lastflowerTime > (1000 / flowerFrequency)) {
// 创建花瓣
let flowerItem = document.createElement('div')
flowerItem.className = 'flower-item'
flowerItem.style.top = -flowerItem.offsetWidth 'px'
// 在给花瓣随机分配横向坐标时,范围应该把花瓣的偏移量也算进去,否则屏幕右下角会出现空白
let _left = (screenWidth Math.tan(flowerAngle * Math.PI / 180) * screenHeight) * Math.random()
flowerItem.style.left = _left 'px'
// 增加随机透明度
// flowerItem.style.opacity = Math.random()
document.body.appendChild(flowerItem)
// 给花瓣一个随机的放大系数,之后运动速度要和这个系数相乘
flowerItem.flowerScale = Math.random() * 0.5 0.5
flowerItem.style.width = flowerItem.offsetWidth * flowerItem.flowerScale 'px'
flowerItem.style.height = flowerItem.offsetHeight * flowerItem.flowerScale 'px'
// 花瓣移动
let flowerMove = () => {
// 此处的花瓣移动速度要和当前花瓣的移动系数相乘
let moveY = flowerSpeed * flowerItem.flowerScale
flowerItem.style.top = flowerItem.offsetTop moveY 'px'
// 根据设置的花瓣偏移角度和纵向移动距离计算花瓣的横向移动距离
let moveX = Math.tan(flowerAngle * Math.PI / 180) * moveY
flowerItem.style.left = flowerItem.offsetLeft - moveX 'px'
// 如果花瓣偏移角度大于0,则判断花瓣是否超出左侧屏幕
if (flowerAngle > 0) {
if (flowerItem.offsetLeft < (-flowerItem.offsetWidth)) {
document.body.removeChild(flowerItem)
return
}
}
// 如果花瓣距离屏幕顶部距离大于等于屏幕高度,则移除此花瓣
if (flowerItem.offsetTop > screenHeight) {
document.body.removeChild(flowerItem)
} else {
requestAnimationFrame(flowerMove)
}
}
flowerMove()
lastflowerTime = now
}
createflowerInterval = requestAnimationFrame(flowerStart)
}
flowerStart()
下面我们再来看一看成品