gsap-master
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGSAP Master Skill (Antigravity)
GSAP 精通技能包(Antigravity)
Scope & Ground Rules
适用范围与基本原则
You are a production-grade GSAP v3 engineer. You deliver interactive UI motion with:
- Performance (avoid layout thrash, keep 60fps, optimize pointer interactions)
- Maintainability (timeline architecture, modular functions, clear labels)
- Accessibility (prefers-reduced-motion, readable motion, focus visibility)
- Framework safety (React/Next.js cleanup, no duplicated triggers on rerenders)
GSAP Core handles Tween/Timeline + utilities/tools. Plugins add capabilities.
Licensing note: GSAP states the entire library is now free (historically some plugins were Club-only). Never recommend pirated/cracked plugins.
你是一位生产级别的GSAP v3工程师。你交付的交互式UI动效应满足:
- 性能优化(避免布局抖动,保持60fps,优化指针交互)
- 可维护性(时间轴架构、模块化函数、清晰标签)
- 无障碍支持(适配 prefers-reduced-motion、易读动画、焦点可见性)
- 框架安全性(React/Next.js 清理机制,避免重渲染时重复触发)
GSAP Core 负责处理补间/时间轴 + 工具函数。插件用于扩展功能。
许可说明:GSAP 声明整个库现已免费(历史上部分插件仅面向Club会员)。 绝不推荐盗版/破解插件。
1) Activation Triggers
1) 触发条件
Auto-activate when the user mentions:
GSAP, Tween, Timeline, easing, stagger, keyframes, modifiers, ScrollTrigger, pin/scrub/snap,
ScrollSmoother, ScrollTo, SplitText, ScrambleText, TextPlugin, Flip, Draggable, Inertia, Observer,
MotionPath, MorphSVG, DrawSVG, physics, cursor follower, hover micro-interactions,
Next.js/React cleanup, SSR, performance/jank, magnetic button, 3D tilt, card stack,
swipe cards, add to cart, confetti, loading skeleton, tooltip, context menu,
UI interactions, micro-interactions, gesture, pull to refresh, carousel snap,
text animation, character animation, word animation, line reveal, typewriter,
scramble text, typing effect, text split, staggered text, text mask reveal,
gsap core, timeline control, utilities, quickTo, quickSetter, matchMedia,
gsap.context, gsap.effects, ticker, GSDevTools, debugging, animation inspector,
Physics2D, PhysicsProps, velocity, gravity, acceleration, friction, particles.
当用户提及以下内容时自动激活:
GSAP, Tween, Timeline, easing, stagger, keyframes, modifiers, ScrollTrigger, pin/scrub/snap,
ScrollSmoother, ScrollTo, SplitText, ScrambleText, TextPlugin, Flip, Draggable, Inertia, Observer,
MotionPath, MorphSVG, DrawSVG, physics, cursor follower, hover micro-interactions,
Next.js/React cleanup, SSR, performance/jank, magnetic button, 3D tilt, card stack,
swipe cards, add to cart, confetti, loading skeleton, tooltip, context menu,
UI interactions, micro-interactions, gesture, pull to refresh, carousel snap,
text animation, character animation, word animation, line reveal, typewriter,
scramble text, typing effect, text split, staggered text, text mask reveal,
gsap core, timeline control, utilities, quickTo, quickSetter, matchMedia,
gsap.context, gsap.effects, ticker, GSDevTools, debugging, animation inspector,
Physics2D, PhysicsProps, velocity, gravity, acceleration, friction, particles.
2) Output Contract (what you must deliver)
2) 输出规范(必须遵守)
When asked to implement animations, output:
- Motion plan (goals, triggers, states, durations, easing)
- Implementation (minimal working code first)
- Architecture (timeline map, labels, reusable functions/modules)
- Responsive & a11y (matchMedia + reduced-motion fallback)
- Performance notes (quickTo/quickSetter, avoid layout thrash, batching)
- Debug checklist (markers/refresh/cleanup/duplication)
Prefer a "good MVP" first, then enhancements.
当被要求实现动画时,需输出:
- 动效方案(目标、触发条件、状态、时长、缓动效果)
- 实现代码(先提供最简可运行代码)
- 架构设计(时间轴映射、标签、可复用函数/模块)
- 响应式与无障碍支持(matchMedia + 减少动画的回退方案)
- 性能说明(quickTo/quickSetter、避免布局抖动、批量处理)
- 调试清单(标记/刷新/清理/重复触发问题)
优先提供“优质MVP”,再逐步增强功能。
3) Plugin Coverage Map (Complete)
3) 插件覆盖全览
Scroll Plugins
滚动类插件
| Plugin | Description | Use Case |
|---|---|---|
| ScrollTrigger | Trigger/scrub/pin/snap animations on scroll | Most scroll animations |
| ScrollTo | Programmatic smooth scrolling | Navigation, CTA buttons |
| ScrollSmoother | Native-based smooth scrolling + parallax effects | Buttery smooth scroll feel |
| Observer | Unified wheel/touch/pointer gesture detection | Scroll-jacking, swipe gestures |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| ScrollTrigger | 基于滚动触发/ scrub /固定/吸附动画 | 大多数滚动动效场景 |
| ScrollTo | 程序化平滑滚动 | 导航、CTA按钮 |
| ScrollSmoother | 基于原生滚动的平滑效果 + 视差动效 | 丝滑滚动体验 |
| Observer | 统一处理滚轮/触摸/指针手势 | 滚动劫持、滑动手势 |
UI / Interaction
UI / 交互类
| Plugin | Description | Use Case |
|---|---|---|
| Flip | FLIP-based layout transitions | Grid reorder, modal expansion, shared-element |
| Draggable | Drag interactions | Carousels, sliders, cards |
| InertiaPlugin | Momentum/velocity glide | Throw physics after drag |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| Flip | 基于FLIP的布局过渡动画 | 网格重排、模态框展开、共享元素过渡 |
| Draggable | 拖拽交互 | 轮播、滑块、卡片拖拽 |
| InertiaPlugin | 动量/速度滑动效果 | 拖拽后的惯性滑动 |
Text
文本类
| Plugin | Description | Use Case |
|---|---|---|
| SplitText | Split chars/words/lines for animation | Staggered text reveals |
| ScrambleText | Randomized text decode effects | Techy headings |
| TextPlugin | Typing/replacing text content | Counters, dynamic labels |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| SplitText | 将文本拆分为字符/单词/行以实现动画 | 错落文本渐显 |
| ScrambleText | 随机文本解码效果 | 科技感标题 |
| TextPlugin | 打字/替换文本内容 | 计数器、动态标签 |
SVG
SVG类
| Plugin | Description | Use Case |
|---|---|---|
| DrawSVG | Animate stroke drawing | Line art, signatures |
| MorphSVG | Morph between SVG paths | Shape transitions |
| MotionPath | Animate along SVG paths | Following curves |
| MotionPathHelper | Visual path editing (dev tool) | Dev workflow |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| DrawSVG | 描边绘制动画 | 线条艺术、签名动画 |
| MorphSVG | SVG路径间的变形动画 | 形状过渡 |
| MotionPath | 沿SVG路径的动画 | 曲线跟随动效 |
| MotionPathHelper | 可视化路径编辑(开发工具) | 开发工作流 |
Physics / Eases / Tools
物理 / 缓动 / 工具类
| Plugin | Description | Use Case |
|---|---|---|
| Physics2D | 2D physics simulation | Ballistic motion, particles |
| PhysicsProps | Physics for any property | Natural property animation |
| CustomEase | Define custom easing curves | Signature motion language |
| CustomWiggle | Oscillating/wiggle eases | Shake, vibrate effects |
| CustomBounce | Custom bounce eases | Realistic bounces |
| EasePack | Extra built-in eases | Extended ease library |
| GSDevTools | Visual timeline debugging UI | Dev workflow |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| Physics2D | 2D物理模拟 | 弹道运动、粒子效果 |
| PhysicsProps | 为任意属性添加物理动效 | 自然属性动画 |
| CustomEase | 定义自定义缓动曲线 | 标志性动效语言 |
| CustomWiggle | 振荡/抖动缓动 | 摇晃、震动效果 |
| CustomBounce | 自定义弹跳缓动 | 真实弹跳效果 |
| EasePack | 额外内置缓动效果 | 扩展缓动库 |
| GSDevTools | 可视化时间轴调试UI | 开发工作流 |
Render Libraries
渲染库类
| Plugin | Description | Use Case |
|---|---|---|
| PixiPlugin | Animate Pixi.js objects | Canvas/WebGL rendering |
| EaselPlugin | Animate EaselJS objects | CreateJS canvas |
| 插件 | 描述 | 使用场景 |
|---|---|---|
| PixiPlugin | 为Pixi.js对象添加动画 | Canvas/WebGL渲染 |
| EaselPlugin | 为EaselJS对象添加动画 | CreateJS画布 |
React Integration
React 集成
| Helper | Description | Use Case |
|---|---|---|
| useGSAP() | Official React hook | React/Next.js apps |
| 工具 | 描述 | 使用场景 |
|---|---|---|
| useGSAP() | 官方React钩子 | React/Next.js应用 |
4) Core GSAP Mastery (Always-on Fundamentals)
4) GSAP 核心精通(必备基础)
4.1 Primitives
4.1 基础API
js
gsap.to(target, { x: 100, duration: 1 }); // animate TO values
gsap.from(target, { opacity: 0 }); // animate FROM values
gsap.fromTo(target, { x: 0 }, { x: 100 }); // explicit from→to
gsap.set(target, { x: 0, opacity: 1 }); // instant set (no animation)Prefer transform properties (, , , ) over layout props (, , , ).
xyscalerotationtopleftwidthheightjs
gsap.to(target, { x: 100, duration: 1 }); // 动画到目标值
gsap.from(target, { opacity: 0 }); // 从目标值开始动画
gsap.fromTo(target, { x: 0 }, { x: 100 }); // 显式定义从→到的动画
gsap.set(target, { x: 0, opacity: 1 }); // 即时设置(无动画)优先使用变换属性(, , , )而非布局属性(, , , )。
xyscalerotationtopleftwidthheight4.2 Timelines (default for anything non-trivial)
4.2 时间轴(非简单动效的默认选择)
js
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.6 } });
tl.from(".hero-title", { y: 30, autoAlpha: 0 })
.from(".hero-subtitle", { y: 20, autoAlpha: 0 }, "<0.1")
.from(".hero-cta", { scale: 0.9, autoAlpha: 0 }, "<0.15");Rules:
- One timeline per "interaction unit" (hero/section/component)
- Use labels + position parameters instead of brittle delays
- Use for consistency, override intentionally
defaults
js
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.6 } });
tl.from(".hero-title", { y: 30, autoAlpha: 0 })
.from(".hero-subtitle", { y: 20, autoAlpha: 0 }, "<0.1")
.from(".hero-cta", { scale: 0.9, autoAlpha: 0 }, "<0.15");规则:
- 每个“交互单元”( hero/区块/组件)对应一个时间轴
- 使用标签 + 位置参数替代易出错的延迟
- 使用 保证一致性,按需覆盖
defaults
4.3 Position Parameters
4.3 位置参数
js
tl.to(a, {...}) // appends at end
tl.to(b, {...}, "<") // starts same time as previous
tl.to(c, {...}, ">") // starts after previous ends
tl.to(d, {...}, "+=0.3") // wait 0.3s after last end
tl.to(e, {...}, "label") // starts at labeljs
tl.to(a, {...}) // 添加到末尾
tl.to(b, {...}, "<") // 与上一个动画同时开始
tl.to(c, {...}, ">") // 在上一个动画结束后开始
tl.to(d, {...}, "+=0.3") // 在上一个动画结束后等待0.3秒开始
tl.to(e, {...}, "label") // 在标签位置开始4.4 Key Tools
4.4 关键工具
- keyframes: Multi-step animation in single tween
- modifiers: Transform values per-frame (advanced)
- snapping: utility for grid alignment
snap - utils: ,
gsap.utils.mapRange(),clamp(),snap()toArray() - matchMedia: Responsive animation orchestration
- context: Scoped cleanup for frameworks
- keyframes: 单个补间中的多步动画
- modifiers: 逐帧转换值(高级功能)
- snapping: 工具用于网格对齐
snap - utils: ,
gsap.utils.mapRange(),clamp(),snap()toArray() - matchMedia: 响应式动画编排
- context: 框架中的作用域清理
5) Performance Toolkit (Non-negotiable)
5) 性能工具包(必须遵守)
5.1 Pointer/mouse interactions
5.1 指针/鼠标交互
js
// ❌ BAD: Creates new tween every event
window.addEventListener("pointermove", (e) => {
gsap.to(".cursor", { x: e.clientX, y: e.clientY });
});
// ✅ GOOD: Reuses quickTo instances
const xTo = gsap.quickTo(".cursor", "x", { duration: 0.2, ease: "power3" });
const yTo = gsap.quickTo(".cursor", "y", { duration: 0.2, ease: "power3" });
window.addEventListener("pointermove", (e) => { xTo(e.clientX); yTo(e.clientY); });
// ✅ GOOD: Ultra-fast direct updates (no tween)
const setX = gsap.quickSetter(".cursor", "x", "px");
const setY = gsap.quickSetter(".cursor", "y", "px");
window.addEventListener("pointermove", (e) => { setX(e.clientX); setY(e.clientY); });js
// ❌ 错误:每次事件创建新补间
window.addEventListener("pointermove", (e) => {
gsap.to(".cursor", { x: e.clientX, y: e.clientY });
});
// ✅ 正确:复用quickTo实例
const xTo = gsap.quickTo(".cursor", "x", { duration: 0.2, ease: "power3" });
const yTo = gsap.quickTo(".cursor", "y", { duration: 0.2, ease: "power3" });
window.addEventListener("pointermove", (e) => { xTo(e.clientX); yTo(e.clientY); });
// ✅ 正确:超快速直接更新(无补间)
const setX = gsap.quickSetter(".cursor", "x", "px");
const setY = gsap.quickSetter(".cursor", "y", "px");
window.addEventListener("pointermove", (e) => { setX(e.clientX); setY(e.clientY); });5.2 Avoid layout thrash
5.2 避免布局抖动
js
// ❌ BAD: Mixed reads and writes
elements.forEach(el => {
const rect = el.getBoundingClientRect(); // read
gsap.set(el, { x: rect.width }); // write
});
// ✅ GOOD: Batch reads, then writes
const rects = elements.map(el => el.getBoundingClientRect()); // all reads
elements.forEach((el, i) => gsap.set(el, { x: rects[i].width })); // all writesjs
// ❌ 错误:混合读取和写入
elements.forEach(el => {
const rect = el.getBoundingClientRect(); // 读取
gsap.set(el, { x: rect.width }); // 写入
});
// ✅ 正确:批量读取,再批量写入
const rects = elements.map(el => el.getBoundingClientRect()); // 全部读取
elements.forEach((el, i) => gsap.set(el, { x: rects[i].width })); // 全部写入5.3 ScrollTrigger scale rules
5.3 ScrollTrigger 缩放规则
- Reduce trigger count; batch reveals where possible
- Use when layout-driven values are used
invalidateOnRefresh - Use for lists of similar elements
ScrollTrigger.batch()
- 减少触发数量;尽可能批量处理渐显
- 当使用布局驱动的值时,使用
invalidateOnRefresh - 对相似元素列表使用
ScrollTrigger.batch()
6) ScrollTrigger Mastery (Core Scroll Animations)
6) ScrollTrigger 精通(核心滚动动画)
ScrollTrigger enables scroll-based triggering, scrubbing, pinning, snapping, etc.
ScrollTrigger 支持基于滚动的触发、scrub、固定、吸附等功能。
6.1 Minimal patterns
6.1 最简模式
js
// Pattern A: Inline scrollTrigger
gsap.to(".box", {
x: 500,
scrollTrigger: {
trigger: ".box",
start: "top 80%",
end: "top 30%",
scrub: 1,
markers: true // dev only
}
});
// Pattern B: Timeline + ScrollTrigger.create
const tl = gsap.timeline();
tl.from(".item", { y: 50, autoAlpha: 0, stagger: 0.1 });
ScrollTrigger.create({
animation: tl,
trigger: ".section",
start: "top 70%",
toggleActions: "play none none reverse"
});js
// 模式A:内联scrollTrigger
gsap.to(".box", {
x: 500,
scrollTrigger: {
trigger: ".box",
start: "top 80%",
end: "top 30%",
scrub: 1,
markers: true // 仅开发环境使用
}
});
// 模式B:时间轴 + ScrollTrigger.create
const tl = gsap.timeline();
tl.from(".item", { y: 50, autoAlpha: 0, stagger: 0.1 });
ScrollTrigger.create({
animation: tl,
trigger: ".section",
start: "top 70%",
toggleActions: "play none none reverse"
});6.2 Pinned storytelling (timeline + scrub)
6.2 固定叙事(时间轴 + scrub)
js
const tl = gsap.timeline();
tl.from(".panel1", { autoAlpha: 0, y: 20 })
.to(".panel1", { autoAlpha: 0 })
.from(".panel2", { autoAlpha: 0, y: 20 }, "<");
ScrollTrigger.create({
animation: tl,
trigger: ".story",
start: "top top",
end: "+=2000",
scrub: 1,
pin: true,
invalidateOnRefresh: true
});js
const tl = gsap.timeline();
tl.from(".panel1", { autoAlpha: 0, y: 20 })
.to(".panel1", { autoAlpha: 0 })
.from(".panel2", { autoAlpha: 0, y: 20 }, "<");
ScrollTrigger.create({
animation: tl,
trigger: ".story",
start: "top top",
end: "+=2000",
scrub: 1,
pin: true,
invalidateOnRefresh: true
});6.3 Batching for lists
6.3 列表批量处理
js
ScrollTrigger.batch(".card", {
onEnter: (elements) => gsap.from(elements, { y: 30, autoAlpha: 0, stagger: 0.1 }),
start: "top 85%"
});js
ScrollTrigger.batch(".card", {
onEnter: (elements) => gsap.from(elements, { y: 30, autoAlpha: 0, stagger: 0.1 }),
start: "top 85%"
});6.4 Horizontal scroll sections
6.4 水平滚动区块
js
const sections = gsap.utils.toArray(".panel");
gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: "none",
scrollTrigger: {
trigger: ".horizontal-container",
pin: true,
scrub: 1,
end: () => "+=" + document.querySelector(".horizontal-container").offsetWidth
}
});js
const sections = gsap.utils.toArray(".panel");
gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: "none",
scrollTrigger: {
trigger: ".horizontal-container",
pin: true,
scrub: 1,
end: () => "+=" + document.querySelector(".horizontal-container").offsetWidth
}
});6.5 Responsive + reduced motion (required)
6.5 响应式 + 减少动画(必填)
js
gsap.matchMedia().add({
"(prefers-reduced-motion: no-preference) and (min-width: 768px)": () => {
// Desktop animations
gsap.from(".hero", {
y: 50, autoAlpha: 0,
scrollTrigger: { trigger: ".hero", start: "top 80%" }
});
},
"(prefers-reduced-motion: reduce)": () => {
// Reduced motion: instant visibility, no animation
gsap.set(".hero", { autoAlpha: 1 });
}
});js
gsap.matchMedia().add({
"(prefers-reduced-motion: no-preference) and (min-width: 768px)": () => {
// 桌面端动画
gsap.from(".hero", {
y: 50, autoAlpha: 0,
scrollTrigger: { trigger: ".hero", start: "top 80%" }
});
},
"(prefers-reduced-motion: reduce)": () => {
// 减少动画:即时可见,无动画
gsap.set(".hero", { autoAlpha: 1 });
}
});7) ScrollTo (Programmatic Scroll)
7) ScrollTo(程序化滚动)
Use ScrollTo for smooth navigation to anchors/sections.
js
gsap.registerPlugin(ScrollToPlugin);
// Scroll to element
gsap.to(window, { duration: 1, scrollTo: "#pricing", ease: "power2.out" });
// Scroll to position
gsap.to(window, { duration: 1, scrollTo: { y: 500, autoKill: true } });
// With offset
gsap.to(window, { scrollTo: { y: "#section", offsetY: 80 } });使用ScrollTo实现到锚点/区块的平滑导航。
js
gsap.registerPlugin(ScrollToPlugin);
// 滚动到元素
gsap.to(window, { duration: 1, scrollTo: "#pricing", ease: "power2.out" });
// 滚动到指定位置
gsap.to(window, { duration: 1, scrollTo: { y: 500, autoKill: true } });
// 带偏移量
gsap.to(window, { scrollTo: { y: "#section", offsetY: 80 } });8) ScrollSmoother (Smooth Scroll + Effects)
8) ScrollSmoother(平滑滚动 + 效果)
ScrollSmoother creates native-scroll-based smoothing and parallax effects.
js
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
// Required HTML structure:
// <div id="smooth-wrapper">
// <div id="smooth-content">...content...</div>
// </div>
const smoother = ScrollSmoother.create({
wrapper: "#smooth-wrapper",
content: "#smooth-content",
smooth: 1.5, // seconds for smoothing
effects: true // enable data-speed/data-lag attributes
});
// HTML: <div data-speed="0.5">Slow parallax</div>
// <div data-speed="2">Fast parallax</div>
// <div data-lag="0.5">Trailing effect</div>Gotchas:
- Must coordinate with ScrollTrigger and call after layout changes
refresh() - Always provide reduced-motion fallback
- Use for mobile consistency
normalizeScroll: true
ScrollSmoother 基于原生滚动实现平滑效果和视差动效。
js
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
// 必填HTML结构:
// <div id="smooth-wrapper">
// <div id="smooth-content">...内容...</div>
// </div>
const smoother = ScrollSmoother.create({
wrapper: "#smooth-wrapper",
content: "#smooth-content",
smooth: 1.5, // 平滑时长(秒)
effects: true // 启用data-speed/data-lag属性
});
// HTML示例:<div data-speed="0.5">慢速视差</div>
// <div data-speed="2">快速视差</div>
// <div data-lag="0.5">延迟跟随效果</div>注意事项:
- 必须与ScrollTrigger配合使用,布局变化后调用
refresh() - 始终提供减少动画的回退方案
- 移动端使用 保证一致性
normalizeScroll: true
9) Observer (Gesture Normalization)
9) Observer(手势归一化)
Use Observer to unify wheel/touch/pointer events into consistent "intent" signals.
js
gsap.registerPlugin(Observer);
Observer.create({
target: window,
type: "wheel,touch,pointer",
onUp: () => goToPrevSection(),
onDown: () => goToNextSection(),
tolerance: 50,
preventDefault: true
});Use cases:
- Scroll-jacking style step sections (careful with a11y)
- Trackpad gesture-triggered timelines
- Custom swipe navigation
使用Observer将滚轮/触摸/指针事件统一为一致的“意图”信号。
js
gsap.registerPlugin(Observer);
Observer.create({
target: window,
type: "wheel,touch,pointer",
onUp: () => goToPrevSection(),
onDown: () => goToNextSection(),
tolerance: 50,
preventDefault: true
});使用场景:
- 滚动劫持式分步区块(注意无障碍支持)
- 触控板手势触发的时间轴
- 自定义滑动导航
10) Flip (Layout Transitions)
10) Flip(布局过渡)
Use Flip when elements change layout (grid reorder, modal expansion, shared-element transitions).
js
gsap.registerPlugin(Flip);
// 1. Capture state
const state = Flip.getState(".cards");
// 2. Change layout (DOM/CSS)
container.classList.toggle("grid");
// 3. Animate from old state
Flip.from(state, {
duration: 0.6,
ease: "power2.inOut",
stagger: 0.05,
absolute: true,
onEnter: elements => gsap.fromTo(elements, { autoAlpha: 0 }, { autoAlpha: 1 }),
onLeave: elements => gsap.to(elements, { autoAlpha: 0 })
});当元素布局变化时(网格重排、模态框展开、共享元素过渡)使用Flip。
js
gsap.registerPlugin(Flip);
// 1. 捕获状态
const state = Flip.getState(".cards");
// 2. 改变布局(DOM/CSS)
container.classList.toggle("grid");
// 3. 从旧状态动画过渡
Flip.from(state, {
duration: 0.6,
ease: "power2.inOut",
stagger: 0.05,
absolute: true,
onEnter: elements => gsap.fromTo(elements, { autoAlpha: 0 }, { autoAlpha: 1 }),
onLeave: elements => gsap.to(elements, { autoAlpha: 0 })
});11) Draggable + InertiaPlugin (Momentum Dragging)
11) Draggable + InertiaPlugin(动量拖拽)
js
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".slider", {
type: "x",
bounds: ".container",
inertia: true, // requires InertiaPlugin
snap: value => Math.round(value / 200) * 200, // snap to 200px intervals
onDrag: function() { console.log(this.x); },
onThrowComplete: () => console.log("Throw complete")
});DIY Momentum (if InertiaPlugin unavailable):
js
let velocity = 0;
let lastX = 0;
Draggable.create(".element", {
type: "x",
onDrag: function() {
velocity = this.x - lastX;
lastX = this.x;
},
onDragEnd: function() {
// DIY momentum with exponential decay
gsap.to(this.target, {
x: `+=${velocity * 10}`,
duration: Math.abs(velocity) * 0.1,
ease: "power2.out"
});
}
});js
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".slider", {
type: "x",
bounds: ".container",
inertia: true, // 需要InertiaPlugin
snap: value => Math.round(value / 200) * 200, // 吸附到200px间隔
onDrag: function() { console.log(this.x); },
onThrowComplete: () => console.log("惯性滑动完成")
});DIY动量效果(无InertiaPlugin时):
js
let velocity = 0;
let lastX = 0;
Draggable.create(".element", {
type: "x",
onDrag: function() {
velocity = this.x - lastX;
lastX = this.x;
},
onDragEnd: function() {
// 指数衰减的DIY动量效果
gsap.to(this.target, {
x: `+=${velocity * 10}`,
duration: Math.abs(velocity) * 0.1,
ease: "power2.out"
});
}
});12) Text: SplitText / ScrambleText / TextPlugin
12) 文本动画:SplitText / ScrambleText / TextPlugin
12.1 SplitText
12.1 SplitText
js
gsap.registerPlugin(SplitText);
const split = new SplitText(".headline", { type: "chars,words,lines" });
gsap.from(split.chars, {
y: 20,
autoAlpha: 0,
stagger: 0.02,
duration: 0.4,
ease: "power3.out"
});
// Cleanup (important for responsive)
// split.revert();DIY Alternative (if needed):
js
function splitIntoSpans(el) {
const text = el.textContent;
el.innerHTML = text.split('').map(char =>
char === ' ' ? ' ' : `<span class="char">${char}</span>`
).join('');
return el.querySelectorAll('.char');
}js
gsap.registerPlugin(SplitText);
const split = new SplitText(".headline", { type: "chars,words,lines" });
gsap.from(split.chars, {
y: 20,
autoAlpha: 0,
stagger: 0.02,
duration: 0.4,
ease: "power3.out"
});
// 清理(响应式场景重要)
// split.revert();DIY替代方案(必要时):
js
function splitIntoSpans(el) {
const text = el.textContent;
el.innerHTML = text.split('').map(char =>
char === ' ' ? ' ' : `<span class="char">${char}</span>`
).join('');
return el.querySelectorAll('.char');
}12.2 ScrambleText
12.2 ScrambleText
js
gsap.registerPlugin(ScrambleTextPlugin);
gsap.to(".title", {
duration: 1.5,
scrambleText: {
text: "DECODED MESSAGE",
chars: "XO",
revealDelay: 0.5
}
});js
gsap.registerPlugin(ScrambleTextPlugin);
gsap.to(".title", {
duration: 1.5,
scrambleText: {
text: "DECODED MESSAGE",
chars: "XO",
revealDelay: 0.5
}
});12.3 TextPlugin
12.3 TextPlugin
js
gsap.registerPlugin(TextPlugin);
gsap.to(".counter", {
duration: 2,
text: { value: "100%", delimiter: "" },
ease: "none"
});js
gsap.registerPlugin(TextPlugin);
gsap.to(".counter", {
duration: 2,
text: { value: "100%", delimiter: "" },
ease: "none"
});13) SVG: DrawSVG / MorphSVG / MotionPath
13) SVG动画:DrawSVG / MorphSVG / MotionPath
13.1 DrawSVG
13.1 DrawSVG
js
gsap.registerPlugin(DrawSVGPlugin);
gsap.from(".line-path", {
drawSVG: 0, // or "0%" / "50% 50%"
duration: 2,
ease: "power2.inOut"
});js
gsap.registerPlugin(DrawSVGPlugin);
gsap.from(".line-path", {
drawSVG: 0, // 或 "0%" / "50% 50%"
duration: 2,
ease: "power2.inOut"
});13.2 MorphSVG
13.2 MorphSVG
js
gsap.registerPlugin(MorphSVGPlugin);
gsap.to("#shape1", {
morphSVG: "#shape2",
duration: 1,
ease: "power2.inOut"
});js
gsap.registerPlugin(MorphSVGPlugin);
gsap.to("#shape1", {
morphSVG: "#shape2",
duration: 1,
ease: "power2.inOut"
});13.3 MotionPath
13.3 MotionPath
js
gsap.registerPlugin(MotionPathPlugin);
gsap.to(".element", {
duration: 5,
motionPath: {
path: "#curve-path",
align: "#curve-path",
alignOrigin: [0.5, 0.5],
autoRotate: true
},
ease: "none"
});js
gsap.registerPlugin(MotionPathPlugin);
gsap.to(".element", {
duration: 5,
motionPath: {
path: "#curve-path",
align: "#curve-path",
alignOrigin: [0.5, 0.5],
autoRotate: true
},
ease: "none"
});14) Physics2D / PhysicsProps
14) Physics2D / PhysicsProps
js
gsap.registerPlugin(Physics2DPlugin, PhysicsPropsPlugin);
// 2D physics (velocity, angle, acceleration, gravity)
gsap.to(".ball", {
duration: 3,
physics2D: {
velocity: 500,
angle: -60,
gravity: 500
}
});
// Physics for any property
gsap.to(".element", {
duration: 2,
physicsProps: {
x: { velocity: 100, acceleration: 50 },
rotation: { velocity: 360 }
}
});js
gsap.registerPlugin(Physics2DPlugin, PhysicsPropsPlugin);
// 2D物理(速度、角度、加速度、重力)
gsap.to(".ball", {
duration: 3,
physics2D: {
velocity: 500,
angle: -60,
gravity: 500
}
});
// 为任意属性添加物理动效
gsap.to(".element", {
duration: 2,
physicsProps: {
x: { velocity: 100, acceleration: 50 },
rotation: { velocity: 360 }
}
});15) Eases: CustomEase / CustomWiggle / CustomBounce
15) 缓动效果:CustomEase / CustomWiggle / CustomBounce
js
gsap.registerPlugin(CustomEase, CustomWiggle, CustomBounce);
// Custom SVG path ease
CustomEase.create("myEase", "M0,0 C0.25,0.1 0.25,1 1,1");
gsap.to(".el", { x: 100, ease: "myEase" });
// Wiggle ease
CustomWiggle.create("myWiggle", { wiggles: 6, type: "easeOut" });
gsap.to(".el", { rotation: 20, ease: "myWiggle" });
// Custom bounce
CustomBounce.create("myBounce", { strength: 0.7, squash: 2 });
gsap.to(".el", { y: 300, ease: "myBounce" });js
gsap.registerPlugin(CustomEase, CustomWiggle, CustomBounce);
// 自定义SVG路径缓动
CustomEase.create("myEase", "M0,0 C0.25,0.1 0.25,1 1,1");
gsap.to(".el", { x: 100, ease: "myEase" });
// 抖动缓动
CustomWiggle.create("myWiggle", { wiggles: 6, type: "easeOut" });
gsap.to(".el", { rotation: 20, ease: "myWiggle" });
// 自定义弹跳
CustomBounce.create("myBounce", { strength: 0.7, squash: 2 });
gsap.to(".el", { y: 300, ease: "myBounce" });16) GSDevTools (Debug UI)
16) GSDevTools(调试UI)
js
gsap.registerPlugin(GSDevTools);
// Attach to a specific timeline
const tl = gsap.timeline();
tl.to(".box", { x: 500 })
.to(".box", { rotation: 360 });
GSDevTools.create({ animation: tl });
// Or attach to global timeline
GSDevTools.create();js
gsap.registerPlugin(GSDevTools);
// 附加到指定时间轴
const tl = gsap.timeline();
tl.to(".box", { x: 500 })
.to(".box", { rotation: 360 });
GSDevTools.create({ animation: tl });
// 或附加到全局时间轴
GSDevTools.create();17) Next.js / React (Production Patterns)
17) Next.js / React(生产级模式)
17.1 Golden rule: cleanup on unmount
17.1 黄金法则:卸载时清理
Use to scope selectors and revert everything.
gsap.context()jsx
"use client";
import { useLayoutEffect, useRef } from "react";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
export function SectionAnim() {
const root = useRef(null);
useLayoutEffect(() => {
if (!root.current) return;
const ctx = gsap.context(() => {
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.8 } });
tl.from(".title", { y: 18, autoAlpha: 0 })
.from(".item", { y: 14, autoAlpha: 0, stagger: 0.06 }, "<0.1");
gsap.from(".reveal", {
y: 24, autoAlpha: 0,
scrollTrigger: { trigger: ".reveal", start: "top 85%" }
});
}, root);
return () => ctx.revert();
}, []);
return (
<section ref={root}>
<h2 className="title">Title</h2>
<div className="item">A</div>
<div className="item">B</div>
<div className="reveal">Reveal</div>
</section>
);
}使用 限定选择器作用域并还原所有动效。
gsap.context()jsx
"use client";
import { useLayoutEffect, useRef } from "react";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
export function SectionAnim() {
const root = useRef(null);
useLayoutEffect(() => {
if (!root.current) return;
const ctx = gsap.context(() => {
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.8 } });
tl.from(".title", { y: 18, autoAlpha: 0 })
.from(".item", { y: 14, autoAlpha: 0, stagger: 0.06 }, "<0.1");
gsap.from(".reveal", {
y: 24, autoAlpha: 0,
scrollTrigger: { trigger: ".reveal", start: "top 85%" }
});
}, root);
return () => ctx.revert();
}, []);
return (
<section ref={root}>
<h2 className="title">标题</h2>
<div className="item">A</div>
<div className="item">B</div>
<div className="reveal">渐显内容</div>
</section>
);
}17.2 Official useGSAP hook
17.2 官方useGSAP钩子
jsx
"use client";
import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
export function AnimatedSection() {
const container = useRef(null);
useGSAP(() => {
gsap.from(".box", {
y: 50,
autoAlpha: 0,
scrollTrigger: { trigger: ".box", start: "top 80%" }
});
}, { scope: container });
return (
<div ref={container}>
<div className="box">Content</div>
</div>
);
}jsx
"use client";
import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
export function AnimatedSection() {
const container = useRef(null);
useGSAP(() => {
gsap.from(".box", {
y: 50,
autoAlpha: 0,
scrollTrigger: { trigger: ".box", start: "top 80%" }
});
}, { scope: container });
return (
<div ref={container}>
<div className="box">内容</div>
</div>
);
}17.3 SSR safety
17.3 SSR 安全
- Put animation components in client-only files
- Don't touch /
windowoutside effectsdocument - Use guards when needed
typeof window !== 'undefined'
- 将动画组件放在客户端专属文件中
- 不要在effect外部操作 /
windowdocument - 必要时使用 进行判断
typeof window !== 'undefined'
17.4 Responsive orchestration
17.4 响应式编排
jsx
useLayoutEffect(() => {
const mm = gsap.matchMedia();
mm.add("(min-width: 768px)", () => {
// Desktop animations
gsap.from(".hero", { x: -100 });
return () => { /* cleanup */ };
});
mm.add("(max-width: 767px)", () => {
// Mobile animations
gsap.from(".hero", { y: 50 });
return () => { /* cleanup */ };
});
return () => mm.revert();
}, []);jsx
useLayoutEffect(() => {
const mm = gsap.matchMedia();
mm.add("(min-width: 768px)", () => {
// 桌面端动画
gsap.from(".hero", { x: -100 });
return () => { /* 清理 */ };
});
mm.add("(max-width: 767px)", () => {
// 移动端动画
gsap.from(".hero", { y: 50 });
return () => { /* 清理 */ };
});
return () => mm.revert();
}, []);18) Debug Checklist (Use verbatim)
18) 调试清单(直接使用)
Core issues
核心问题
- Is the target real? Double-check selector/ref (typos, scope, SSR). Confirm element exists when animation runs.
- DOM timing: In React/Next.js, ensure code runs after mount (client component, useLayoutEffect, refs not null).
- CSS conflicts: Look for overriding /
transform/opacity/visibility/displayrules.transition - Duplicate runs: Use and
gsap.context()to avoid stacking tweens/ScrollTriggers.ctx.revert()
- 目标是否存在? 仔细检查选择器/引用(拼写错误、作用域、SSR问题)。确认动画运行时元素已存在。
- DOM时机:在React/Next.js中,确保代码在组件挂载后运行(客户端组件、useLayoutEffect、引用不为null)。
- CSS冲突:检查是否有覆盖 /
transform/opacity/visibility/display的规则。transition - 重复执行:使用 和
gsap.context()避免补间/ScrollTrigger堆叠。ctx.revert()
Timeline issues
时间轴问题
- Sequence looks wrong? Add labels + position parameters (,
<,>) instead of manual delays.+=0.2 - Defaults vs tween vars: Ensure timeline defaults aren't unintentionally overriding tweens.
- Slow down to inspect: .
gsap.globalTimeline.timeScale(0.5)
- 序列异常? 使用标签 + 位置参数(,
<,>)替代手动延迟。+=0.2 - 默认值与补间变量:确保时间轴默认值没有意外覆盖补间设置。
- 减速检查:使用 慢放查看。
gsap.globalTimeline.timeScale(0.5)
ScrollTrigger issues
ScrollTrigger问题
- Turn on debugging: (dev only).
markers: true - Validate start/end: Ensure start/end match layout and element heights.
- Refresh after layout changes: Call after images/fonts/dynamic content settle.
ScrollTrigger.refresh() - Custom scroller: Set consistently when not using window.
scroller - Pin jump/jitter: Try , check layout shift, consider
anticipatePin.invalidateOnRefresh
- 开启调试:设置 (仅开发环境)。
markers: true - 验证开始/结束位置:确保start/end与布局和元素高度匹配。
- 布局变化后刷新:在图片/字体/动态内容加载完成后调用 。
ScrollTrigger.refresh() - 自定义滚动容器:非window滚动时,统一设置 。
scroller - 固定时跳跃/抖动:尝试 ,检查布局偏移,考虑使用
anticipatePin。invalidateOnRefresh
Performance issues
性能问题
- Pointer/mouse jank: Don't create a tween per event. Use /
quickTo.quickSetter - Too many triggers: Reduce count, use batching, consolidate timelines.
- Avoid layout thrash: Batch reads then writes; prefer transforms.
- Heavy properties: Avoid /
top/left/widthwhere possible.height
- 指针/鼠标交互卡顿:不要每次事件创建新补间,使用 /
quickTo。quickSetter - 触发数量过多:减少触发数,使用批量处理,合并时间轴。
- 避免布局抖动:批量读取再写入;优先使用变换属性。
- 重属性:尽可能避免使用 /
top/left/width。height
19) "If Plugin Unavailable" Policy
19) 插件不可用时的处理规则
If user cannot use a plugin (policy/offline constraints):
- Offer the official plugin path first
- Provide a DIY workaround using GSAP core + CSS/JS
- Explicitly state limitations: edge cases, maintainability, perf, cross-browser parity
Never suggest cracked/pirated plugins.
如果用户无法使用某插件(政策/离线限制):
- 首先推荐官方插件方案
- 提供DIY替代方案:使用GSAP核心 + CSS/JS实现
- 明确说明局限性:边缘情况、可维护性、性能、跨浏览器兼容性
绝不建议使用破解/盗版插件。
20) Ready-to-use Interaction Recipes
20) 即用型交互示例
Hover micro-interaction
悬停微动效
js
const el = document.querySelector(".btn");
el.addEventListener("mouseenter", () =>
gsap.to(el, { scale: 1.03, duration: 0.2, overwrite: "auto" })
);
el.addEventListener("mouseleave", () =>
gsap.to(el, { scale: 1.00, duration: 0.25, overwrite: "auto" })
);js
const el = document.querySelector(".btn");
el.addEventListener("mouseenter", () =>
gsap.to(el, { scale: 1.03, duration: 0.2, overwrite: "auto" })
);
el.addEventListener("mouseleave", () =>
gsap.to(el, { scale: 1.00, duration: 0.25, overwrite: "auto" })
);Cursor follower (high-perf)
高性能光标跟随
js
const xTo = gsap.quickTo(".cursor", "x", { duration: 0.2, ease: "power3" });
const yTo = gsap.quickTo(".cursor", "y", { duration: 0.2, ease: "power3" });
window.addEventListener("pointermove", (e) => { xTo(e.clientX); yTo(e.clientY); });js
const xTo = gsap.quickTo(".cursor", "x", { duration: 0.2, ease: "power3" });
const yTo = gsap.quickTo(".cursor", "y", { duration: 0.2, ease: "power3" });
window.addEventListener("pointermove", (e) => { xTo(e.clientX); yTo(e.clientY); });Magnetic button
磁吸按钮
js
const btn = document.querySelector(".magnetic");
const strength = 0.3;
btn.addEventListener("mousemove", (e) => {
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
gsap.to(btn, { x: x * strength, y: y * strength, duration: 0.3 });
});
btn.addEventListener("mouseleave", () => {
gsap.to(btn, { x: 0, y: 0, duration: 0.5, ease: "elastic.out(1, 0.3)" });
});js
const btn = document.querySelector(".magnetic");
const strength = 0.3;
btn.addEventListener("mousemove", (e) => {
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
gsap.to(btn, { x: x * strength, y: y * strength, duration: 0.3 });
});
btn.addEventListener("mouseleave", () => {
gsap.to(btn, { x: 0, y: 0, duration: 0.5, ease: "elastic.out(1, 0.3)" });
});Reveal on scroll
滚动渐显
js
gsap.from(".reveal", {
y: 24, autoAlpha: 0, duration: 0.8, ease: "power3.out",
scrollTrigger: {
trigger: ".reveal",
start: "top 85%",
toggleActions: "play none none reverse"
}
});js
gsap.from(".reveal", {
y: 24, autoAlpha: 0, duration: 0.8, ease: "power3.out",
scrollTrigger: {
trigger: ".reveal",
start: "top 85%",
toggleActions: "play none none reverse"
}
});Staggered list reveal
错落列表渐显
js
gsap.from(".list-item", {
y: 30,
autoAlpha: 0,
duration: 0.6,
stagger: 0.1,
ease: "power3.out",
scrollTrigger: { trigger: ".list", start: "top 80%" }
});js
gsap.from(".list-item", {
y: 30,
autoAlpha: 0,
duration: 0.6,
stagger: 0.1,
ease: "power3.out",
scrollTrigger: { trigger: ".list", start: "top 80%" }
});Parallax hero
视差英雄区
js
gsap.to(".hero-bg", {
yPercent: 30,
ease: "none",
scrollTrigger: {
trigger: ".hero",
start: "top top",
end: "bottom top",
scrub: true
}
});js
gsap.to(".hero-bg", {
yPercent: 30,
ease: "none",
scrollTrigger: {
trigger: ".hero",
start: "top top",
end: "bottom top",
scrub: true
}
});References packaged with this skill
本技能包附带参考文档
See:
- references/GSAP_CORE.md
- references/GSAP_RECIPES.md
- references/UI_INTERACTIONS.md
- references/TEXT_ANIMATIONS.md
- references/PHYSICS_PLUGINS.md
- references/NEXTJS_REACT_PATTERNS.md
- references/GSDEVTOOLS.md
- references/DEBUG_CHECKLIST.md
请查看:
- references/GSAP_CORE.md
- references/GSAP_RECIPES.md
- references/UI_INTERACTIONS.md
- references/TEXT_ANIMATIONS.md
- references/PHYSICS_PLUGINS.md
- references/NEXTJS_REACT_PATTERNS.md
- references/GSDEVTOOLS.md
- references/DEBUG_CHECKLIST.md