4、缓动函数艺术:内置缓动函数与cubic-bezier()自定义曲线
动画做出来生硬还是流畅,关键就在缓动函数。
说白了,缓动函数就是控制动画速度变化的工具。没有它,所有动画都是匀速的,像机器人一样僵硬。我刚开始做前端时,觉得动画嘛,能动就行。后来被设计师怼了几次,才真正重视起这个细节。
4.1 五个内置缓动函数
CSS 给我们准备了五个现成的缓动函数。它们覆盖了大部分日常场景。
| 函数名 | 效果描述 | 适用场景 |
|---|---|---|
linear |
全程匀速,没有加速减速 | 进度条、加载旋转 |
ease |
慢→快→慢,默认值 | 通用过渡,最自然 |
ease-in |
慢→快,起步慢 | 元素进入、弹窗出现 |
ease-out |
快→慢,结尾慢 | 元素消失、按钮反馈 |
ease-in-out |
慢→快→慢,两头慢 | 轮播切换、卡片翻转 |
核心记忆点:ease-in 适合「进来」,ease-out 适合「出去」。别搞反了,否则看起来像在跟用户较劲。
/* 基础用法 */
.box {
transition: transform 0.3s ease-out;
}
.box:hover {
transform: scale(1.1);
}
嗯,这里要注意:ease 是默认值。如果你不写 transition-timing-function,浏览器就用 ease。但我不建议依赖默认值——显式写出来,代码可读性更好,别人一看就知道你的意图。
4.2 cubic-bezier():真正的控制权
内置函数虽然方便,但不够灵活。比如你想让动画先快后慢再快,内置函数就做不到了。
这时候就需要 cubic-bezier()。它用四个参数定义一条贝塞尔曲线,控制动画速度的变化。
/* 语法:cubic-bezier(x1, y1, x2, y2) */
.custom-ease {
transition: transform 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
}
四个参数对应两个控制点的坐标。x 值必须在 0 到 1 之间,y 值可以超出范围——超出就会产生「回弹」效果。
我的小技巧:别硬记参数。用 Chrome DevTools 的动画调试面板,拖拽曲线实时预览,找到感觉再复制参数。我每次做新项目都会打开它调一调。
4.3 打造真实物理感
为什么有些动画看起来「假」?因为现实世界没有匀速运动。物体启动时有惯性,停止时有阻力。
我做过一个卡片拖拽排序的功能。一开始用 ease-out,总觉得卡片「飘」过去的,不像被手拖动的。后来换成自定义贝塞尔曲线,才找到那种「被拽着走」的感觉。
/* 模拟弹簧效果 */
.spring {
transition: transform 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
/* 模拟重力下落 */
.fall {
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
/* 模拟弹性碰撞 */
.bounce {
transition: transform 0.5s cubic-bezier(0.5, 1.5, 0.5, -0.5);
}
我曾经踩过的坑:y 值超出 [0, 1] 范围会产生回弹效果,看起来很酷。但回弹幅度太大,或者动画时间太短,会让用户觉得「晃眼」。尤其是按钮这种高频交互,回弹要克制。我一般把回弹幅度控制在 0.3 以内。
4.4 实战:弹窗动画
来,我们做一个完整的弹窗动画。要求:弹窗从底部滑入,先快后慢,带一点弹性。
.modal {
transform: translateY(100%);
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.modal.active {
transform: translateY(0);
}
为什么选这个曲线?0.34, 1.56 让开头加速快一点,0.64, 1 让结尾减速自然。y 值 1.56 超出 1,产生轻微回弹——弹窗到位后会「抖」一下,很像真实物理碰撞。
你想想看,如果换成 ease-out,弹窗会匀速滑入然后突然停住,像撞墙一样。加了回弹后,用户会觉得「这东西有重量」。
4.5 常用曲线速查表
我整理了一份自己常用的曲线表,直接复制就能用。
| 效果 | cubic-bezier 参数 | 说明 |
|---|---|---|
| 标准缓入 | 0.42, 0, 1, 1 |
等同于 ease-in |
| 标准缓出 | 0, 0, 0.58, 1 |
等同于 ease-out |
| 柔和缓出 | 0.25, 0.1, 0.25, 1 |
比 ease-out 更平滑 |
| 弹性进入 | 0.68, -0.55, 0.27, 1.55 |
过头再回弹 |
| 重力下落 | 0.22, 1, 0.36, 1 |
先慢后快再慢 |
| 快速弹起 | 0.5, 1.5, 0.5, -0.5 |
适合点赞动画 |
我的建议:先掌握 ease-out 和 ease-in-out,能解决 80% 的场景。剩下的 20% 再用自定义曲线精调。别一上来就搞复杂曲线,容易翻车。
4.6 避坑指南
最后说几个我踩过的坑。
- 动画时间太短:回弹效果需要时间展现。如果
duration小于 0.3s,回弹还没完成就结束了,看起来像抖动。我一般给回弹动画留 0.5s 以上。 - 多个属性用不同曲线:同时改变
opacity和transform时,可以用不同缓动函数。比如透明度用ease,位移用cubic-bezier。这样动画层次更丰富。 - 别忘了无障碍:有些用户设置了「减少动画」偏好。用
prefers-reduced-motion媒体查询,给这些用户提供无动画版本。我曾经忽略这个,被用户投诉过。
/* 尊重用户偏好 */
@media (prefers-reduced-motion: reduce) {
.modal {
transition: none;
}
}
缓动函数是动画的灵魂。花时间调好它,你的页面会从「能动」变成「舒服」。下一章我们聊关键帧动画,到时候这些曲线知识会派上大用场。