返回文章列表
技术

非线性动画:给界面装上惯性

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 的思路是:

  1. First:记录旧位置
  2. Last:改完 DOM 记录新位置
  3. Invert:用 transform 把它"拉回"旧位置
  4. Play:动画到 0

全程只动 transform,不触发布局,60fps 稳如老狗。本站的标签筛选就是这么做的——你可以去文章页点几个标签试试。

#一条硬规则

只动画 transformopacity。其他属性一律先想办法绕开。

widthtopmargin 会触发重排;box-shadowfilter 会触发重绘。想要柔光边缘?用一个绝对定位的伪元素做 opacity 过渡,别去动 box-shadow

余烬电台

40 首 · 网易云源