前言
在周末假期闲下来的时间,捣鼓了一个新的小效果,用 CSS和JS实现的一个树苗生长的效果。整个实现过程比较简单,大家可以先看到下面的效果预览部分,十分简单,没有花里胡哨的技巧。话不多说,咱们直接进入主题。
效果预览
最终实现的相关效果如下。
HTML部分
首先看到HTML部分。相关代码如下。
<figure class="sapling">
<div class="branch"></div>
<div class="leaves">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</figure>
这里创建了一个简单的树苗(sapling)的视觉表示,主要由两部分组成,树干(branch)和树叶(leaves)。<figure class="sapling">定义了一个容器,类名为 sapling。
<div class="branch"></div>表示一个空的 div,类名为 branch,代表树枝。
<div class="leaves"> 包含6个 <span> 元素,每个 <span> 代表一片叶子。
这里描述了树苗的结构,实际的视觉效果依赖接下来的CSS定义。
CSS部分
首先是树苗容器 (sapling)样式,相关代码如下。
.sapling {
width: 5em;
height: 17.5em;
font-size: 10px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
定义树苗的宽高(基于 font-size: 10px,1em = 10px),position: relative使内部 absolute 定位的子元素(branch 和 leaves)相对于它定位。display: flex + align-items: center + justify-content: center使树干和树叶居中。
其次是树干 (branch)样式,相关代码如下。
.branch {
position: absolute;
width: 0.2em;
height: inherit;
background-color: burlywood;
border-radius: 25%;
transform-origin: bottom;
}
这里定义一个浅棕色树干,加上一些轻微圆角,使树干更自然。
然后是树叶容器 (leaves)样式,相关代码如下。
.leaves {
position: absolute;
width: inherit;
height: 80%;
display: flex;
flex-direction: column-reverse;
}
position: absolute:相对于 .sapling 定位,树叶区域占树苗高度的 80%。flex-direction: column-reverse使 <span> 从下往上排列。
还有树叶 (leaves span)样式,相关代码如下。
.leaves span {
width: 2.5em;
height: 2.5em;
background-color: limegreen;
}
.leaves span:nth-child(odd) {
align-self: flex-start;
border-top-right-radius: 3em;
border-bottom-left-radius: 3em;
transform-origin: right bottom;
}
.leaves span:nth-child(even) {
align-self: flex-end;
border-top-left-radius: 3em;
border-bottom-right-radius: 3em;
transform-origin: left bottom;
}
定义好每片叶子是 2.5em × 2.5em(25px × 25px),绿色背景。
align-self: flex-start靠左对齐,定义右上和左下圆角,形成斜向椭圆,并让旋转原点在右下角(可用于风吹动画)。
align-self: flex-end靠右对齐,定义左上和右下圆角,与奇数叶子对称,旋转原点在左下角。
JS部分
树苗效果已经实现好了,接下来就是实现生长的效果了,可以通过过动画实现,也可以通过JS脚本实现,这里咱们用JS方法来实现树苗生长的过程。相关代码如下。
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
<script>
let $branch = '.branch';
let $leaves = '.leaves span';
let animation = new TimelineMax({repeat: -1, repeatDelay: 0.5});
animation.from($branch, 4, {scaleY: 0, ease: Power1.easeOut}, 'branch')
.staggerFrom($leaves, 0.5, {scale: 0, ease: Power1.easeOut}, 0.5, 0.5, 'branch')
.to([$branch, $leaves], 3, {backgroundColor: 'yellow'})
.to([$branch, $leaves], 1, {autoAlpha: 0});
</script>
这段代码使用了 GSAP (GreenSock Animation Platform) 的 TimelineMax 来创建一个树苗(sapling)的生长动画,并最终让它消失。以下是逐行解析:
首先是变量定义,$branch 指向树干的 DOM 元素(.branch),$leaves 指向所有树叶的 DOM 元素(.leaves span)。然后是创建动画时间轴,TimelineMax 是 GSAP 的时间轴工具,用于顺序控制多个动画。repeat: -1表示动画无限循环。repeatDelay: 0.5表示每次循环之间暂停 0.5 秒。
实现树干生长(从无到有)只需从初始状态过渡到当前状态。初始状态(高度为 0,即不可见)。ease: Power1.easeOut实现一个缓动效果(先快后慢),最终呈现的效果就是树干从底部向上“生长”出来。
实现树叶依次出现只需对多个元素($leaves)依次应用动画。
$leaves:所有树叶元素。0.5:每个树叶动画时长 0.5 秒。{scale: 0}:初始状态(大小为 0,即不可见)。ease: Power1.easeOut:缓动效果。0.5:每个树叶动画的间隔时间(0.5 秒)。0.5:整个动画的延迟时间(0.5 秒)。'branch':与branch动画同步(树干生长完成后开始)。
最终实现的效果就是树叶从中心向外依次缩放出现(间隔 0.5 秒)。
- 树干生长(4 秒,从无到有)。
- 树叶依次出现(每片 0.5 秒,间隔 0.5 秒)。
- 颜色变黄(3 秒)。
- 淡出消失(1 秒)。
- 循环(重复上述过程,每次循环前暂停 0.5 秒)。
总结
以上就是整个效果的实现过程了,就这样实现了一棵风格化的树苗。代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等,添加 animation 使树叶摇摆(如风吹效果),调整 border-radius 或 transform 让叶子形状更自然。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~