时间轴

Timeline

Timeline 动画时间轴 gsap.timeline 序列动画 Sequence 编排

把多个补间放进一条可整体控制的时间线,用位置参数精确安排先后与重叠,再统一播放、暂停、倒放或跳转。

又称:动画时间轴 · gsap.timeline · 序列动画 · Sequence · 编排

  • GSAP
  • Claude / Cursor
ABC
0.00s
tl.from(a).from(b, '-=0.2').from(c, '+=0.1')

Prompt 片段

  • Claude / Cursor
    用 gsap.timeline 做 Hero 区入场:标题 from y: 40、opacity: 0,副标题比标题提前 0.3 秒结束(位置参数 '-=0.3'),按钮与副标题同时开始('<');timeline 的 defaults 设为 duration 0.6、ease expo.out。
  • Claude / Cursor
    把现有的三段 setTimeout 串起来的动画改写成一个 GSAP timeline,并暴露 play、reverse 方法给按钮使用。
  • Claude / Cursor
    给 timeline 加 onUpdate 回调,把 this.progress() 同步到一个进度条的 scaleX,把 this.time() 显示成保留两位小数的秒数。

是什么

时间轴(Timeline)是 GSAP 用来编排多个补间的容器。用 gsap.timeline() 创建后,链式调用 .to().from().fromTo() 添加动画,默认一个接一个顺序播放。它最重要的能力是位置参数:每个补间的最后一个参数可以指定它在时间线上的插入点,从而精确控制间隔与重叠。

上方演示中,A 先从左侧滑入;B 用 '-=0.2' 在 A 结束前 0.2 秒就开始,两者有重叠;C 用 '+=0.1' 在 B 结束后空出 0.1 秒再开始;最后三者用 stagger 依次轻跳一下。下方的进度条和秒数来自 timeline 的 onUpdate 回调。

核心参数

写法 含义
1.2 绝对时间,从时间线第 1.2 秒开始
'+=0.1' / '-=0.2' 相对时间线末尾,留出间隔或提前重叠
'<' / '>' 上一个补间的开始 / 结束
'<0.2' 上一个补间开始后 0.2 秒
'intro' / 'intro+=0.5' 标签位置,用 tl.addLabel('intro') 添加
defaults 子补间共享的默认值,如 duration、ease

时间轴本身也支持 repeatyoyopaused,以及 play()pause()reverse()seek()progress()timeScale() 等控制方法。

代码示例

import { gsap } from 'gsap';

const bar = document.querySelector('.progress');
const time = document.querySelector('.time');

const tl = gsap.timeline({
  repeat: -1,
  repeatDelay: 1,
  defaults: { duration: 0.6, ease: 'expo.out' },
  onUpdate() {
    bar.style.transform = `scaleX(${this.progress()})`;
    time.textContent = `${this.time().toFixed(2)}s`;
  },
});

tl.from('.a', { x: -120, opacity: 0 })
  .from('.b', { y: 60, rotation: -90, opacity: 0 }, '-=0.2')
  .from('.c', { scaleX: 0 }, '+=0.1')
  .to(['.a', '.b', '.c'], { y: -14, duration: 0.25, ease: 'power2.out', stagger: 0.08, yoyo: true, repeat: 1 });

什么时候用

  • 页面入场、引导动画等多个元素有先后关系的场景。
  • 需要整体暂停、倒放或拖动进度的动画,例如可交互的讲解动画。
  • 与 ScrollTrigger 结合,让一整段叙事动画跟随滚动播放。

常见误区

  • delay 手动串联:改一段时长,后面所有 delay 都要重算。交给位置参数。
  • 在时间轴里放 repeat: -1 的子补间:时间轴时长变成无限,后面的补间永远轮不到。
  • 修改布局后不刷新:用函数值(如 x: () => el.offsetWidth)的补间,需要在尺寸变化后调用 invalidate() 重新计算。
esc