模式 · 24
时间线
Timeline · timeline把几段补间放到同一只时钟上,明确哪些接续、重叠或对齐。
多段动画若各自依赖 setTimeout,改一段时长,后面的开始点就可能全错。时间线把每段的开始、结束与标签一起算出来,重叠关系看得见,也能用同一个播放头拖动检查。
公式
> start at previous end < start at previous start +=.2 start .2 s after previous end <.1 start .1 s after previous start cue start at the named label
参数
| 本页默认 | 成熟实现 | |
|---|---|---|
| position | 每段可选 | GSAP 支持 <、>、相对偏移和标签 |
| duration | 0.55–0.8 s | —本页五段的演示时长。 |
| playhead | 可拖动 | — |
怎样做好
- 用相对位置写“接上一段末尾”“与上一段同时起”,不要把每个起点都写成绝对秒数。GSAP 的位置解析直接以最近一段的起点或终点计算。GSAP src/gsap-core.js:390–413
- 给跨段对齐的位置命名。改前面两段的时长后,引用
cue的段仍和标签对齐。GSAP src/gsap-core.js:403–405 - 需要错开的入场就让各段重叠,不必一段播完才播下一段。
nova的背景、标题和说明分别从 0、0.3、0.42 秒开始。www-motion/rewrite/nova/app.js:10 - 重播或关闭组件时清理旧时间线,避免旧回调覆盖新状态;
formation的详情开关先停止旧时间线。www-motion/rewrite/formation/shutter.js:4–7
在我们的案例里
44 个案例组织了时间线。nova 让背景、标题、正文与卡片在不同绝对时刻重叠进入;formation 则把开关详情的多个阶段串起来。用一根播放头检查这些关系,比逐个调延时更直观。
出现在 44 个案例
参考实现 · basics.js
/**
* Lay out tweens on one clock, GSAP position-parameter style:
* number absolute time '<' same start as previous '>' (default) after previous
* '+=0.2' / '-=0.2' relative to the end of previous '<0.1' relative to previous start 'label'
*/
export function timeline(items) {
const labels = {}; let prevStart = 0, prevEnd = 0;
const placed = items.map(item => {
if (item.label && item.duration == null) { labels[item.label] = prevEnd; return null; }
const p = item.at ?? '>';
let start;
if (typeof p === 'number') start = p;
else if (p in labels) start = labels[p];
else if (p === '<') start = prevStart;
else if (p === '>') start = prevEnd;
else if (p.startsWith('<')) start = prevStart + parseFloat(p.slice(1));
else if (p.startsWith('+=') || p.startsWith('-=')) start = prevEnd + parseFloat(p.replace('=', ''));
else start = prevEnd;
prevStart = start; prevEnd = start + item.duration;
return { ...item, start, end: prevEnd };
}).filter(Boolean);
const duration = Math.max(0, ...placed.map(p => p.end));
return { items: placed, labels, duration,
progressAt: (t, item) => (item.ease || (x => x))(clamp((t - item.start) / item.duration)) };
}