经典动画原则:翻译成引擎参数
其余各页讲引擎能算什么,本页反过来:那些让运动「像真的」的经验法则,具体落到哪个参数上。迪士尼总结的十二条原则里,有五条能干净地映射成引擎参数,且映射之后会发现——它们都不是引擎的新能力,而是关键帧、缓动、弹簧这几个既有原语的用法。
与 CSS 侧的好动画的七条准则互为表里:那边讲什么时候该动、动多久,本页讲同一段运动怎么算得更像真的。
1 · 缓入缓出
真实物体启动要加速、停下要减速,匀速反而最不自然。引擎里就是把 ease 从 linear 换成 easeInOut——一个参数的事,却是五条里最基础也最常被略过的一条。
2 · 预备动作
大动作之前先反向蓄力,观众的眼睛被预告,动作因而更有力。引擎里是在关键帧序列前面插一个反向的途经点:x: [0, -16, 目标],再用 times 把蓄力压在前 22% 的时间里。
注 · 蓄力量与时间占比要一起调。蓄力段若不给 times 而均分时间,反向那一小段会占掉三分之一的时长,看上去不是「蓄力」而是「先往回走了一趟」。图 2-1 里 16 px 的蓄力配 22% 的时间,量小而快,观感才对。
3 · 挤压与拉伸
有弹性的物体受力时形变而体积守恒:触地一刻横向铺开、纵向压扁。引擎里是给 scaleX 与 scaleY 各排一条反相的关键帧,与位置同步,触地点最扁。transform-origin 要设在底部,否则压扁时物体会同时向上收,看着像悬空。
警示 ·「体积守恒」在二维里的严格写法是 ,而图 3-1 用的是 ,并不守恒。这是有意的:严格守恒对应的横向系数是 ,铺得太开,在这个尺寸的圆球上看起来像被踩扁的煎饼。手绘动画里这条原则本就是感觉优先,不是物理约束。
4 · 跟随与重叠
主体停下时,附属部分因惯性继续往前、再回弹归位。引擎里:主体用 easeOut 干脆停住,尾巴改用弹簧带过冲地追上来。两者起点相同、落定不同步,重叠感正来自这个时间差。
5 · 弧线
生物的肢体绕关节转动,轨迹几乎都是弧线;直线位移看起来机械。引擎里让位置的两个分量各走各的:x 匀速推进,y 走一条 [0, -72, 0] 的抛物线,合成出弧。
import { animate } from '@vega/anim';
// 缓入缓出: 整体 ease
animate(el, { x: [0, end] }, { ease: 'easeInOut' });
// 预备: 关键帧序列前插一个反向途经点 (蓄力)
animate(el, { x: [0, -16, end] }, { times: [0, 0.22, 1], ease: 'easeOut' });
// 挤压拉伸: scaleX / scaleY 反相, 与位置同步 (触地点最扁), origin 在底部
animate(el, {
y: [0, floorY, 0],
scaleY: [1, 0.6, 1], // 压扁
scaleX: [1, 1.4, 1], // 铺开
}, { ease: 'easeInOut' });
// 跟随 / 重叠: 主体干脆停, 附属用弹簧带过冲追上
animate(body, { x: [0, end] }, { ease: 'easeOut' });
animate(tail, { x: [0, end] }, { type: 'spring', spring: { stiffness: 180, damping: 12 } });
// 弧线: x / y 分量各走各的, 合成出弧
animate(el, { x: [0, end], y: [0, -72, 0] }, { ease: 'linear' });