关于 gsap
gsap 是一项技能,介绍如何在 FrameVideo 中使用 GSAP 制作脚本动画。内容涵盖定时与嵌套时间轴、注册可定位的暂停时间轴,以及验证合成。
主要功能
- 01创建补间和时间轴
- 02用标签编排动画
- 03制作交错和嵌套动效
- 04注册可定位的 FrameVideo 时间轴
- 05使用 FrameVideo CLI 检查合成
适用场景
- 01编排多元素场景
- 02将动效与旁白节拍同步
- 03制作标题和界面元素动画
- 04为视频渲染创建有限时长动画
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ chanjing-ai/ framevideo --skill gsap安装后在 Claude Code 中输入/gsap确认已加载。
附带文件references/effects.mdscripts/extract-audio-data.py
详细介绍
GSAP
适用场景
以下情况适合使用 GSAP:
- 场景编排 — 多元素序列,时序精准
- 复杂时间线 — 错落动画、标签、嵌套序列
- 文本/卡片动效 — 字幕、标题卡片、UI 元素入场
- 音频同步动画 — 与配音协调、按节拍触发的动效
- 大多数脚本动画 — GSAP 是 FrameVideo 的默认动画适配器
请勿使用
以下情况请避免使用 GSAP:
- 简单装饰性循环 — 使用
css-animations(闪光、脉冲、发光) - 设计师提供的 After Effects 导出文件 — 使用
lottie - 3D 场景和 WebGL — 使用
three - GPU 计算着色器 — 使用
typegpu - 要求零依赖 — 使用
waapi
如有疑问,使用 GSAP — 它用途最广,也是默认选择。
快速入门
在 FrameVideo 中使用 GSAP 创建最简动画:
<div data-composition-id="main" data-width="1920" data-height="1080">
<div class="clip" data-start="0" data-duration="3">
<h1 class="title">Hello GSAP</h1>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
// Fade in and slide up
tl.from(".title", {
y: 48,
opacity: 0,
duration: 0.6,
ease: "power3.out"
}, 0);
window.__timelines["main"] = tl;
</script>
要点:
- 从 CDN 加载 GSAP
- 创建暂停的时间线
- 添加带有时序的补间动画
- 使用匹配的合成 ID,在
window.__timelines上注册时间线
FrameVideo 约定
FrameVideo 通过其 gsap 运行时适配器控制 GSAP。同步创建暂停的时间线,使用完全一致的 data-composition-id 在 window.__timelines 上注册,然后由 FrameVideo 对时间线进行定位。
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
tl.from(".title", { y: 48, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.to(".accent", { scaleX: 1, duration: 0.5, ease: "power2.out" }, 0.25);
window.__timelines["main"] = tl; // key must equal data-composition-id on the composition root
</script>
- 注册表键必须与合成根元素的
data-composition-id一致。 - 对于渲染关键动效,请勿调用
tl.play()。 - 请勿在异步代码、计时器或事件处理程序中创建时间线。
- 循环次数必须有限。FrameVideo 渲染的是时长有限的视频。
核心补间方法
- gsap.to(targets, vars) — 从当前状态动画到
vars。最常用。 - gsap.from(targets, vars) — 从
vars动画到当前状态(入场动画)。 - gsap.fromTo(targets, fromVars, toVars) — 显式指定起始和结束状态。
- gsap.set(targets, vars) — 立即应用(时长为 0)。
属性名始终使用小驼峰命名法(例如 backgroundColor、rotationX)。
常用 vars
- duration — 时长,单位为秒(默认值为 0.5)。
- delay — 开始前的延迟,单位为秒。
- ease —
"power1.out"(默认值)、"power3.inOut"、"back.out(1.7)"、"elastic.out(1, 0.3)"、"none"。 - stagger — 数字
0.1或对象:{ amount: 0.3, from: "center" }、{ each: 0.1, from: "random" }。 - overwrite —
false(默认值)、true或"auto"。 - repeat — 有限次数;在 FrameVideo 中绝不可设为
-1。根据可见时长计算重复次数。yoyo — 每次重复时反转方向。 - onComplete、onStart、onUpdate — 回调函数。
- immediateRender — from()/fromTo() 的默认值为
true。后续补间若作用于相同的属性和元素,请设为false,以避免覆盖。
变换和 CSS
优先使用 GSAP 的变换别名,而非原始 transform 字符串:
| GSAP 属性 | 对应属性 |
|---|---|
x、y、z | translateX/Y/Z(px) |
xPercent、yPercent | translateX/Y(%) |
scale、scaleX、scaleY | scale |
rotation | rotate(度) |
rotationX、rotationY | 3D 旋转 |
skewX、skewY | skew |
transformOrigin | transform-origin |
- autoAlpha — 优先于
opacity。值为 0 时还会设置visibility: hidden。 - CSS 变量 —
"--hue": 180。 - svgOrigin (仅限 SVG) — 全局 SVG 坐标空间原点。不要与
transformOrigin一起使用。 - 定向旋转 —
"360_cw"、"-170_short"、"90_ccw"。 - clearProps —
"all"或逗号分隔的属性;完成时移除内联样式。 - 相对值 —
"+=20"、"-=10"、"*=2"。
函数式值
gsap.to(".item", {
x: (i, target, targets) => i * 50,
stagger: 0.1,
});
缓动
内置缓动:power1–power4、back、bounce、circ、elastic、expo、sine。每种都提供 .in、.out、.inOut。
默认值
gsap.defaults({ duration: 0.6, ease: "power2.out" });
控制补间动画
const tween = gsap.to(".box", { x: 100 });
tween.pause();
tween.play();
tween.reverse();
tween.kill();
tween.progress(0.5);
tween.time(0.2);
gsap.matchMedia()(响应式 + 无障碍)
仅当媒体查询匹配时运行设置;不再匹配时自动还原。
let mm = gsap.matchMedia();
mm.add(
{
isDesktop: "(min-width: 800px)",
reduceMotion: "(prefers-reduced-motion: reduce)",
},
(context) => {
const { isDesktop, reduceMotion } = context.conditions;
gsap.to(".box", {
rotation: isDesktop ? 360 : 180,
duration: reduceMotion ? 0 : 2,
});
},
);
时间轴
创建时间轴
const tl = gsap.timeline({ defaults: { duration: 0.5, ease: "power2.out" } });
tl.to(".a", { x: 100 }).to(".b", { y: 50 }).to(".c", { opacity: 0 });
位置参数
第三个参数控制放置位置:
- 绝对位置:
1— 位于 1s 处 - 相对位置:
"+=0.5"— 在结束后;"-=0.2"— 在结束前 - 标签:
"intro"、"intro+=0.3" - 对齐:
"<"— 与上一个动画从同一时间开始;">"— 在上一个动画结束后开始;"<0.2"— 在上一个动画开始后 0.2s 开始
tl.to(".a", { x: 100 }, 0);
tl.to(".b", { y: 50 }, "<"); // same start as .a
tl.to(".c", { opacity: 0 }, "<0.2"); // 0.2s after .b starts
标签
tl.addLabel("intro", 0);
tl.to(".a", { x: 100 }, "intro");
tl.addLabel("outro", "+=0.5");
tl.play("outro");
tl.tweenFromTo("intro", "outro");
时间轴选项
- paused: true — 创建时暂停;调用
.play()开始播放。 - repeat、yoyo — 对整个时间轴生效。
- defaults — 合并到每个子补间动画中的 vars。
嵌套时间轴
const master = gsap.timeline();
const child = gsap.timeline();
child.to(".a", { x: 100 }).to(".b", { y: 50 });
master.add(child, 0);
播放控制
tl.play()、tl.pause()、tl.reverse()、tl.restart()、tl.time(2)、tl.progress(0.5)、tl.kill()。
性能
优先使用变换和透明度
动画化 x、y、scale、rotation、opacity 会在合成器上执行。若变换能实现相同效果,请避免使用 width、height、top、left。
will-change
will-change: transform;
仅用于实际参与动画的元素。
对频繁更新使用 gsap.quickTo()
let xTo = gsap.quickTo("#id", "x", { duration: 0.4, ease: "power3" }),
yTo = gsap.quickTo("#id", "y", { duration: 0.4, ease: "power3" });
container.addEventListener("mousemove", (e) => {
xTo(e.pageX);
yTo(e.pageY);
});
使用 stagger,而非多个补间动画
使用 stagger,而不是通过手动延迟创建多个独立补间动画。
清理
暂停或销毁屏幕外的动画。
参考资料(按需加载)
- references/effects.md — 即用型效果:打字机文本、音频可视化器。需要 FrameVideo 的现成效果模式时阅读。
最佳实践
- 使用 camelCase 属性名;优先使用变换别名和 autoAlpha。
- 优先使用时间轴,而非通过 delay 链接动画;使用位置参数。
- 使用
addLabel()添加标签,让序列更易读。 - 将 defaults 传入时间轴构造函数。
- 控制播放时,保存补间动画/时间轴的返回值。
请勿
- 变换足以满足需求时,避免动画化布局属性(width/height/top/left)。
- 不要在同一个 SVG 元素上同时使用 svgOrigin 和 transformOrigin。
- 时间轴可以编排动画时,不要使用 delay 链接动画。
- DOM 尚未创建时,不要创建补间动画。
- 不要跳过清理——不再需要时,务必销毁补间动画。
- 不要在 FrameVideo 合成中使用无限重复次数。请根据可见时长计算有限的重复次数。
验证
编写 GSAP 动画后:
npx framevideo lint # Check timeline registration and timing
npx framevideo validate # Check for runtime errors
npx framevideo preview # Scrub timeline to verify seekability
手动检查:
- 时间轴注册 — 验证
window.__timelines["main"]与data-composition-id匹配 - 暂停状态 — 时间轴使用
paused: true创建 - 有限时长 — 不存在无限循环或
-1重复次数 - 可定位性 — 拖动预览时间轴,动画应能在任意帧保持不变
- 非异步注册 — 在 FrameVideo 初始化前同步创建时间轴
致谢与参考资料
- FrameVideo 适配器源代码:
packages/core/src/runtime/adapters/gsap.ts。 - GSAP 文档:https://gsap.com/docs/v3/
- GSAP 时间轴暂停和定位行为:https://gsap.com/docs/v3/GSAP/Timeline/pause%28%29/