技术
非线性动画:给界面装上惯性
3 分钟
现实世界里没有匀速运动的物体。任何东西启动都要克服惯性,停下都要耗散动能。
所以 transition: all 0.3s linear 永远看起来像 PPT。
#曲线即性格
我常用的四条曲线,各有各的人设:
| 曲线 | 值 | 性格 |
| --- | --- | --- |
| 指数缓出 | cubic-bezier(.16,1,.3,1) | 冷静、贵气、克制 |
| 轻微过冲 | cubic-bezier(.34,1.45,.5,1) | 俏皮、有弹性 |
| 快进慢出 | cubic-bezier(.7,0,.2,1) | 果断、有力量 |
| 慢进快出 | cubic-bezier(.5,0,1,.4) | 撤离、消失 |
元素进场用缓出,离场用缓入。 这符合视觉焦点:进来的东西要被看清,离开的东西要迅速让位。
#错峰是免费的高级感
同时出现十个元素 = 一堆东西。错开 40ms 依次出现 = 一段叙述。
items.forEach((el, i) => {
el.animate(
[{ opacity: 0, transform: 'translateY(24px)' }, { opacity: 1, transform: 'none' }],
{ duration: 700, delay: i * 42, easing: 'cubic-bezier(.16,1,.3,1)', fill: 'backwards' }
);
});
注意 fill: 'backwards'——没有它,延迟期间元素会先闪一下。这个细节能干掉 90% 的"廉价感"。
#FLIP:让重排也有物理
筛选标签的时候,列表项会跳到新位置。直接跳 = 割裂。FLIP 的思路是:
- First:记录旧位置
- Last:改完 DOM 记录新位置
- Invert:用 transform 把它"拉回"旧位置
- Play:动画到 0
全程只动 transform,不触发布局,60fps 稳如老狗。本站的标签筛选就是这么做的——你可以去文章页点几个标签试试。
#一条硬规则
只动画
transform和opacity。其他属性一律先想办法绕开。
width、top、margin 会触发重排;box-shadow、filter 会触发重绘。想要柔光边缘?用一个绝对定位的伪元素做 opacity 过渡,别去动 box-shadow。