GSAP (GreenSock Animation Platform) 是目前最强大的 JavaScript 动画引擎。自 Webflow 收购后,所有插件均已免费开放,npm install gsap 即可获得全部功能。本文将从核心 API 到高级插件,系统性地梳理 GSAP 的完整能力。
一、Core 核心引擎
核心引擎提供四个基础方法来创建动画,是一切 GSAP 动画的起点。
1.1 gsap.to() — 最常用的动画方法
从当前状态动画到目标状态。几乎所有的动画效果都可以用 gsap.to() 实现:
gsap.to(".box", {
x: 200,
autoAlpha: 1,
duration: 0.6,
ease: "power2.out"
});
1.2 gsap.from() — 入场动画利器
从指定状态动画到当前状态,非常适合做页面加载时的入场效果:
gsap.from(".title", {
y: 50,
autoAlpha: 0,
duration: 0.8
});
1.3 gsap.fromTo() — 精确控制起止
明确指定动画的起点和终点,不依赖元素当前状态:
gsap.fromTo(".bar",
{ width: 0 },
{ width: "100%", duration: 1 }
);
1.4 gsap.set() — 立即设置属性
相当于 duration 为 0 的特殊动画,常用于初始化状态:
gsap.set(".modal", { autoAlpha: 0, y: 20 });
1.5 Transform 别名与 autoAlpha
GSAP 提供了一套比 CSS transform 更高效的快捷属性:x、y、scale、rotation 等直接对应 translateX/Y、scale、rotate。推荐使用 autoAlpha 代替 opacity——当值为 0 时同时设置 visibility: hidden,元素不响应点击也不占用渲染资源。
1.6 Stagger 交错动画
让多个元素依次执行动画,而不是同时开始,是打造精致交互体验的关键:
// 每个 .card 间隔 0.1 秒依次向上弹起
gsap.from(".card", {
y: 40, autoAlpha: 0,
duration: 0.5,
stagger: 0.1
});
// 从中心向两侧扩散
gsap.to(".dot", {
scale: 1.5,
stagger: { amount: 0.6, from: "center" }
});
// 网格交错:适合图片墙
gsap.from(".grid-item", {
scale: 0,
stagger: { amount: 0.8, from: "center", grid: [5, 8] }
});
1.7 Easing 缓动函数
缓动决定了动画的运动节奏。GSAP 内置大量缓动函数,每种都有 .in(加速)、.out(减速)、.inOut(先加速后减速)三种变体:
"power1.out"— 轻微减速,通用首选"power3.inOut"— 两头慢中间快,适合页面切换"back.out(1.7)"— 超过终点再弹回,弹出元素"elastic.out(1, 0.3)"— 弹性抖动,适合强调提醒"bounce.out"— 弹跳落地效果"expo.out"— 急速减速,快速出现
二、Timeline 时间轴
时间轴是 GSAP 的核心优势,用于编排多步动画序列。
2.1 基本用法
const tl = gsap.timeline({
defaults: { duration: 0.5, ease: "power2.out" }
});
tl.to(".logo", { scale: 1.2 })
.to(".title", { autoAlpha: 1 })
.to(".subtitle", { y: 0 })
.to(".cta", { autoAlpha: 1 });
2.2 Position Parameter 位置参数
时间轴最强大的特性——精确控制每个动画的开始时间:
tl.to(".a", { x: 100 }, 0); // 第 0 秒开始
tl.to(".b", { y: 50 }, "+=0.3"); // 上一步结束后 0.3 秒
tl.to(".c", { scale: 2 }, "-=0.2"); // 上一步结束前 0.2 秒(重叠)
tl.to(".d", { rotation: 90 }, "<"); // 和上一步同时开始
tl.to(".e", { x: 50 }, "<0.1"); // 上一步开始后 0.1 秒
2.3 嵌套时间轴
将复杂动画拆分为独立子时间轴,再组合到主时间轴,实现模块化管理:
function introAnimation() {
const tl = gsap.timeline();
tl.from(".logo", { scale: 0, duration: 0.5 })
.from(".nav a", { y: -20, autoAlpha: 0, stagger: 0.1 });
return tl;
}
const master = gsap.timeline();
master.add(introAnimation())
.add(contentAnimation(), "-=0.3");
2.4 播放控制
tl.play(); // 播放
tl.pause(); // 暂停
tl.reverse(); // 倒放
tl.restart(); // 重新开始
tl.progress(0.5); // 跳到 50%
tl.timeScale(2); // 2 倍速
三、ScrollTrigger 滚动触发
将动画与页面滚动绑定,是 GSAP 最受欢迎的插件。
3.1 基本触发
gsap.registerPlugin(ScrollTrigger);
gsap.from(".section", {
y: 60, autoAlpha: 0, duration: 0.8,
scrollTrigger: {
trigger: ".section",
start: "top 80%",
end: "bottom 20%",
toggleActions: "play none none reverse"
}
});
3.2 Scrub 滚动绑定
动画进度完全跟随滚动条位置,实现"滚动驱动"效果:
gsap.to(".progress-bar", {
width: "100%",
scrollTrigger: {
trigger: ".article",
start: "top top",
end: "bottom bottom",
scrub: true // 实时跟随滚动
}
});
3.3 Pin 固定与横向滚动
让元素在滚动范围内固定不动,配合 scrub 可以实现水平滚动等高级效果:
gsap.to(".content", {
xPercent: -100,
ease: "none",
scrollTrigger: {
trigger: ".horizontal-section",
start: "top top",
end: "+=2000",
pin: true,
scrub: 1
}
});
3.4 toggleActions
控制进入/离开触发区域时的四个动作(onEnter、onLeave、onEnterBack、onLeaveBack),每个位置可选:play、pause、resume、reset、restart、complete、reverse、none。
3.5 Batch 批量触发
ScrollTrigger.batch(".card", {
onEnter: (elements) => {
gsap.to(elements, { autoAlpha: 1, y: 0, stagger: 0.15 });
},
start: "top 85%"
});
四、Flip 布局动画
Flip 实现了 FLIP 技术(First, Last, Invert, Play),让任何布局变化都能平滑过渡。核心思路是三步走:
gsap.registerPlugin(Flip);
// 1. 记录当前状态
const state = Flip.getState(".item");
// 2. 改变 DOM(重排、增删元素、切换 class)
container.classList.toggle("grid-layout");
// 3. 从旧状态动画到新状态
Flip.from(state, {
duration: 0.6,
ease: "power2.inOut",
stagger: 0.04
});
典型场景:列表排序动画、网格↔列表切换、卡片展开/折叠、购物车添加商品、照片画廊筛选。
五、Draggable 拖拽
让任何元素可以拖拽、旋转、投掷:
gsap.registerPlugin(Draggable);
Draggable.create(".card", {
type: "x,y",
bounds: "#container",
inertia: true,
edgeResistance: 0.7,
onDragEnd: function() { /* 拖拽结束 */ }
});
支持 "x"、"y"、"x,y"、"rotation" 四种拖拽模式,配合 InertiaPlugin 可以实现释放后的惯性滑动。
六、SplitText 文字拆分
将文本元素拆分为独立的字符、单词、行,用于逐字/逐词/逐行动画:
gsap.registerPlugin(SplitText);
const split = SplitText.create(".heading", { type: "words, chars" });
gsap.from(split.chars, {
autoAlpha: 0, y: 20, rotationX: -90,
stagger: 0.03, duration: 0.4
});
支持 mask 遮罩效果(文字从下方滑出被裁剪)、autoSplit 自动在字体加载或宽度变化时重新拆分,默认设置 aria-label 保障无障碍。
七、SVG 动画插件
7.1 DrawSVG 描边绘制
逐步绘制或擦除 SVG 描边,通过动画 stroke-dashoffset 实现:
gsap.registerPlugin(DrawSVGPlugin);
gsap.from("#path", { drawSVG: 0, duration: 2 });
gsap.to("#path", { drawSVG: "20% 80%", duration: 1 });
7.2 MorphSVG 形状变形
将一个 SVG 形状平滑变形为另一个,起止形状不需要相同数量的锚点:
gsap.registerPlugin(MorphSVGPlugin);
gsap.to("#diamond", {
morphSVG: "#lightning",
duration: 1,
ease: "power2.inOut"
});
7.3 MotionPath 路径运动
让元素沿 SVG 路径移动,支持自动朝向路径切线方向:
gsap.registerPlugin(MotionPathPlugin);
gsap.to(".rocket", {
motionPath: {
path: "#flight-path",
align: "#flight-path",
alignOrigin: [0.5, 0.5],
autoRotate: true
},
duration: 3
});
八、实用工具与性能优化
8.1 gsap.utils 工具函数
GSAP 提供了一组强大的纯函数工具:
clamp(min, max, val)— 限制范围mapRange(a1, a2, b1, b2, val)— 范围映射interpolate(start, end, progress)— 插值(支持数字、颜色、对象)random(min, max)— 随机数snap(increment, val)— 吸附到倍数wrap(min, max, val)— 循环值pipe(f1, f2, ...)— 函数组合
省略最后一个参数可以获得可复用函数:
const clampProgress = gsap.utils.clamp(0, 1);
clampProgress(1.5); // 1
clampProgress(-0.2); // 0
8.2 gsap.quickTo() 高频更新
为频繁更新的属性创建复用 tween,避免每帧创建新实例:
const xTo = gsap.quickTo("#cursor", "x", { duration: 0.4, ease: "power3" });
const yTo = gsap.quickTo("#cursor", "y", { duration: 0.4, ease: "power3" });
document.addEventListener("mousemove", (e) => {
xTo(e.clientX);
yTo(e.clientY);
});
8.3 gsap.matchMedia() 响应式动画
根据媒体查询运行不同动画,条件不匹配时自动清理:
let mm = gsap.matchMedia();
mm.add({
isDesktop: "(min-width: 800px)",
isMobile: "(max-width: 799px)",
reduceMotion: "(prefers-reduced-motion: reduce)"
}, (context) => {
const { isDesktop, reduceMotion } = context.conditions;
gsap.to(".hero", {
x: isDesktop ? 200 : 50,
duration: reduceMotion ? 0 : 1
});
});
8.4 性能最佳实践
| 推荐 | 避免 |
|---|---|
动画 x、y、scale、rotation、opacity | 动画 width、height、top、left(触发布局重排) |
用 autoAlpha 代替 opacity | 用 opacity 隐藏后元素仍可点击 |
用 stagger 代替多个独立 tween | 手动给每个元素创建带 delay 的 tween |
用 gsap.quickTo() 做鼠标跟随 | 在 mousemove 里每帧创建新 tween |
及时 kill() 不再需要的动画 | 让动画在不可见时继续运行 |
九、其他插件速览
- ScrambleText — 乱码/加密效果逐步揭示目标文本,黑客风格
- ScrollToPlugin — 平滑滚动到页面指定位置或元素
- ScrollSmoother — 将原生滚动变为带惯性的丝滑滚动
- Observer — 统一处理触摸、指针、滚轮事件,识别方向和手势
- InertiaPlugin — 配合 Draggable 实现释放后的惯性滑动
- CustomEase — 用贝塞尔曲线或 SVG 路径数据定义任意缓动曲线
- CustomWiggle / CustomBounce — 基于频率和振幅的摆动/弹跳缓动
- Physics2DPlugin — 模拟速度、角度、重力的简单物理运动
- PixiPlugin — 让 GSAP 直接动画 PixiJS 显示对象
- GSDevTools — 可视化调试面板,可拖拽时间轴进度(仅开发环境)
十、框架集成
React
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP);
useGSAP(() => {
gsap.to(".box", { x: 100 });
}, { scope: containerRef });
Vue 3
在 onMounted 中用 gsap.context(),在 onUnmounted 中 ctx.revert() 清理。
Svelte
在 onMount 中用 gsap.context(),返回清理函数 () => ctx.revert()。
所有框架的核心原则:DOM 就绪后创建动画,组件卸载时清理,用 scope 限制选择器范围。