手把手教你实现一个树苗生长的效果

319 阅读4分钟

前言

在周末假期闲下来的时间,捣鼓了一个新的小效果,用 CSSJS实现的一个树苗生长的效果。整个实现过程比较简单,大家可以先看到下面的效果预览部分,十分简单,没有花里胡哨的技巧。话不多说,咱们直接进入主题。

效果预览

最终实现的相关效果如下。

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: 10px1em = 10px),position: relative使内部 absolute 定位的子元素(branchleaves)相对于它定位。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.5em25px × 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 秒)。

  1. 树干生长(4 秒,从无到有)。
  2. 树叶依次出现(每片 0.5 秒,间隔 0.5 秒)。
  3. 颜色变黄(3 秒)。
  4. 淡出消失(1 秒)。
  5. 循环(重复上述过程,每次循环前暂停 0.5 秒)。

总结

以上就是整个效果的实现过程了,就这样实现了一棵风格化的树苗。代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等,添加 animation 使树叶摇摆(如风吹效果),调整 border-radiustransform 让叶子形状更自然。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~