时序:重复、往返与停顿
缓动回答的是「一次迭代之内,进度怎么走」。它上面还有一层:时序(timing)负责把物理流逝的毫秒翻译成「现在是第几次迭代、这次迭代内进度是多少」。一段动画可以重复若干次(repeat),两次重复之间可以停顿(repeatDelay),而重复的方向有三种互不相同的语义。
这两层的分工很干净:时序层只算出「迭代序号 + 迭代内线性进度」这一对数,方向语义与缓动曲线一概不管;拿到这对数之后再交给塑形函数,才产生真正驱动动画的值。
1 · 三种重复方向
loop 每次都从头顺放,进度走到 1 后瞬回 0;reverse 在奇数次迭代上把时间反演;mirror 在奇数次迭代上把值翻转。把整段重复沿总时间展开画成一条曲线,三者的形状差别一目了然。
2 · 方向语义的分岔点
reverse 与 mirror 的差别只发生在塑形这一步。reverse 是
:先翻时间再缓动,缓动曲线本身随之时间反演。mirror 是
:先缓动再翻值,运动关于中点对称,去程与回程的节奏完全一致。
警示 · 缓动对称时两者形状相同。默认的 easeInOut 满足
,切换 reverse 与 mirror 看不出任何区别——这一点上手时很容易误判为「配置没生效」。把缓动换成单向的 easeOut 才能看出分岔,图 1-1 的缓动选择器因此默认给的是 easeOut 而非引擎默认值。
3 · 停顿落在哪里
repeatDelay 插在两次迭代之间,而非迭代之内:进度走到 1 后并不立刻重置,而是停在末端等这段停顿走完,再开始下一次。曲线上表现为顶部(或往返的两端)多出一段水平平台。
整段动画的总时长因此是
停顿只出现在迭代之间,所以乘的是 repeat 而不是 repeat + 1——最后一次迭代结束后不再等待。
单次迭代内的曲线本身见缓动;把多个互不相同的动画排到一条时间轴上(而非同一段反复重复)见关键帧与编排;让这条时序被一个可暂停、可反向的游标驱动见播放控制。