手把手教你实现一个跳动动画

323 阅读4分钟

前言

哈喽大家好,又隔了一个多月,这次我就先带大家来实现一个跳动动画来热热身,全效果由纯CSS实现,十分简单。话不多说,咱们直接进入主题。

效果预览

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

HTML部分

首先我们先看到HTML部分。相关代码如下。

  <figure class="container">
        <span class="girl"></span>
        <div class="boys">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </div>
    </figure>

这里定义了一个 container(容器),其中包含了一个 girl(粉色方块)以及四个 boys(蓝色方块,亮度依次递增)。

类名为 girl 的元素,使用 hotpink 背景色(在 CSS 中会定义),具有 左右滑动动画animation: slide)。内部 4 个 <span> 代表 4 个滑块,每个都有 翻转 + 弹跳动画。可以想象成“女孩跑过去,男孩们被撞飞”的动画场景。

CSS部分

接下来我们看到该动画实现的 CSS 部分。首先是类名为container的动画部分,相关代码如下。

.container {
    width: 8em;
    height: 1em;
    font-size: 35px;
    display: flex;
    justify-content: space-between;
}

.container span {
    width: 1em;
    height: 1em;
    --duration: 1.5s;
}

这里定义了类名为container的元素及其子元素span的样式和布局,建立了基本的布局结构,后续的动画效果都是基于这些尺寸和布局参数实现的。我们可以看到,这里定义了CSS变量--duration供动画使用,方便统一调整动画速度。

然后就是boy,girl的样式部分,相关代码如下。

.boys {
    width: 6em;
    display: flex;
    justify-content: space-between;
}
.boys span {
    transform-origin: -50% center;
    animation: var(--duration) ease-in-out infinite alternate;
}
.boys span:nth-child(1) {
    animation-name: jump-off-1;
}
.boys span:nth-child(2) {
    animation-name: jump-off-2;
}
.boys span:nth-child(3) {
    animation-name: jump-off-3;
}
.boys span:nth-child(4) {
    animation-name: jump-off-4;
}
.girl {
    animation: slide var(--duration) ease-in-out infinite alternate;
}

这里定义了.boys.girl的动画效果,让它们产生协调的动态交互。使用弹性布局,让4个男孩水平排列,均匀分布,两端对齐。总容器宽度是8em,女孩占1em,所以男孩组分配6em(剩下1em是间距)。4个男孩在6em宽度内等距分布(每个男孩占据约1.5em空间)。

transform-origin: -50% center 将旋转中心点设置在元素的左侧外部-50%),这样旋转时会产生"向后倒"的效果(类似杠杆支点在左侧)。

每个男孩都有独立动画(jump-off-1jump-off-4),每个男孩的动画通过@keyframes定义不同的延迟形成依次倒下的波浪效果。从0deg旋转到-180deg(向后翻转),配合transform-origin实现"被推倒"的视觉效果。

接着就是这些动画代码了,相关代码如下。

@keyframes jump-off-1 {
    0%, 15% {
        transform: rotate(0deg);
    }
    35%, 100% {
        transform: rotate(-180deg);
    }
}
@keyframes jump-off-2 {
    0%, 30% {
        transform: rotate(0deg);
    }
    50%, 100% {
        transform: rotate(-180deg);
    }
}
@keyframes jump-off-3 {
    0%, 45% {
        transform: rotate(0deg);
    }
    65%, 100% {
        transform: rotate(-180deg);
    }
}
@keyframes jump-off-4 {
    0%, 60% {
        transform: rotate(0deg);
    }
    80%, 100% {
        transform: rotate(-180deg);
    }
}
@keyframes slide {
    to {
        transform: translatex(calc(8em - (1em * 1.25)));
        filter: brightness(1.45);
    }
}

这段代码定义了四个关键帧动画(jump-off-1 到 jump-off-4),用于控制四个蓝色方块("男孩")的依次向后旋转倒下的动画效果。

所有 jump-off 动画都有相同的模式

  • 初始状态:保持 0deg(直立)一段时间
  • 最终状态:旋转到 -180deg(完全向后倒下)
  • 差异化延迟:每个男孩的开始旋转时间逐渐推迟

slide 动画中,通过 translateX() 在 0 到 (8em - 1.25em) 之间移动,滑动时亮度 brightness(1.45) 变亮。

男孩们(.boys span 动画中,翻转动画jump-off-1 到 jump-off-4),每个男孩依次旋转 -180deg(像被推倒一样)。通过 nth-child 设置不同的延迟(15%30%45%60%)。弹跳动画jump-down-1 到 jump-down-4),使用 scale() 模拟“压扁→拉长→恢复”的弹跳效果。每个男孩的动画比前一个稍晚触发(形成波浪效果)。

当女孩滑动到右侧时,第一个男孩快速倒下(15%-35%时间),第二个男孩稍晚开始倒下(30%-50%时间),第三个和第四个男孩依次延迟倒下,女孩返回时,所有男孩反向执行动画(由于 alternate 属性)。

这种设计创造了非常流畅的"撞击传递"效果,每个男孩的倒下动作都显得自然且有节奏感。

总结

以上就是整个效果的实现过程了,纯 CSS 实现,代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~