mcpField
G
gsap

gsap

github.com/chanjing-ai创意与媒体0179 次安装14 周前更新
代码仓库

关于 gsap

gsap 是一项技能,介绍如何在 FrameVideo 中使用 GSAP 制作脚本动画。内容涵盖定时与嵌套时间轴、注册可定位的暂停时间轴,以及验证合成。

主要功能

  1. 01创建补间和时间轴
  2. 02用标签编排动画
  3. 03制作交错和嵌套动效
  4. 04注册可定位的 FrameVideo 时间轴
  5. 05使用 FrameVideo CLI 检查合成

适用场景

  1. 01编排多元素场景
  2. 02将动效与旁白节拍同步
  3. 03制作标题和界面元素动画
  4. 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>

要点:

  1. 从 CDN 加载 GSAP
  2. 创建暂停的时间线
  3. 添加带有时序的补间动画
  4. 使用匹配的合成 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、ztranslateX/Y/Z(px)
xPercent、yPercenttranslateX/Y(%)
scale、scaleX、scaleYscale
rotationrotate(度)
rotationX、rotationY3D 旋转
skewX、skewYskew
transformOrigintransform-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

手动检查:

  1. 时间轴注册 — 验证 window.__timelines["main"] 与 data-composition-id 匹配
  2. 暂停状态 — 时间轴使用 paused: true 创建
  3. 有限时长 — 不存在无限循环或 -1 重复次数
  4. 可定位性 — 拖动预览时间轴,动画应能在任意帧保持不变
  5. 非异步注册 — 在 FrameVideo 初始化前同步创建时间轴

致谢与参考资料

评论

支持 Markdown