从补间到叙事:GSAP 动画实战 · 公开阅读
第1章 GSAP 概述
了解 GSAP 的用途、安装方式,并创建第一个动画。
本章小节
1.1 GSAP 是什么
有些网站打开的瞬间,元素像被施了魔法一样优雅地滑入、旋转、淡入——那些丝滑的产品页面和令人惊艳的着陆页动画,背后大概率是 GSAP 在干活。
GSAP(GreenSock Animation Platform)是一套 JavaScript 动画工具。核心计算属性的中间值,CSSPlugin 等插件将值写入 DOM;Canvas 和 WebGL 场景由你的绘制代码呈现。动画能否流畅,需要结合页面和设备测量。
1.2 发展简史
GSAP 源于 GreenSock 在 ActionScript/Flash 时代的补间工具,后来发展为 JavaScript 动画库。理解今天的 API,重点是区分旧版本语法与 GSAP 3。
- GSAP 3.0 在 2019 年发布,整合了 TweenLite/TweenMax 等入口。
- ScrollTrigger、Flip、Observer 等插件补充滚动、布局和输入处理。
- GSAP 3.13 将此前的会员插件纳入公开安装包。参见 3.13 发布说明。
本书使用 gsap.to()、gsap.from() 和 gsap.timeline()。阅读旧教程时,先核对版本、插件名称和安装方式。
1.3 为什么选择 GSAP
1.3.1 先区分计算与渲染
GSAP 使用帧循环,根据时间和缓动计算属性值。DOM 是否需要布局、绘制或合成,仍由浏览器决定;使用 GSAP 不会绕过浏览器渲染成本。
1.3.2 按需求选择工具
| 需求 | 可考虑的实现 | 判断依据 |
|---|---|---|
| 简单悬停、颜色过渡 | CSS transition | 状态少,无需脚本编排 |
| 原生可控制动画 | Web Animations API | 浏览器支持与控制需求 |
| 多段串行、并行、逆放 | GSAP Timeline | 可组合的播放头和位置参数 |
| 滚动联动、布局过渡、SVG 变形 | GSAP 对应插件 | 实际功能与项目体积 |
| Canvas / Three.js 属性动画 | GSAP + 绘制器 | GSAP 更新值,绘制器负责显示 |
没有统一的帧率排名。比较时要使用相同 DOM、属性、目标设备和测量条件,记录布局、绘制和主线程耗时。
1.3.3 使用边界
GSAP 不要求 React 或 Vue,但会写入元素的内联样式;SplitText 会临时修改文本 DOM。卸载时用 context.revert() 恢复已记录的样式,拆分文本等资源也要还原。仅 kill() 会停止动画,不等于把页面恢复到动画之前。
1.4 GSAP 3.x 架构概览
GSAP 3.x 采用核心 + 插件模式:核心自带基础功能,高级功能通过插件扩展。
gsap (核心)
├── gsap.to() / gsap.from() / gsap.fromTo() ← 三大核心 API
├── gsap.timeline() ← 时间线
├── gsap.registerPlugin() ← 插件注册
├── gsap.set() ← 零时间设置
├── gsap.utils ← 工具方法
├── gsap.eases ← 缓动函数库
└── 插件
├── ScrollTrigger —— 滚动驱动动画
├── Flip —— 布局变化动画
├── ScrollTo —— 平滑滚动
├── Draggable —— 拖拽交互
├── MorphSVG —— SVG 形变
├── DrawSVG —— SVG 描边动画
└── MotionPath —— 路径跟随动画GSAP 3.13 起,核心与全部插件都免费,包括商业使用。MorphSVG、DrawSVG、SplitText 等均包含在公开的 gsap npm 包中,无需 Club GSAP 会员或私有仓库令牌。详见 官方发布说明。
1.5 安装与引入
下面三种方式,按你的场景选择:
方式一:CDN(最快上手)
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.13.0/gsap.min.js"></script>方式二:npm(工程化项目)
npm install gsapimport gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);方式三:ES Module CDN
<script type="module">
import gsap from 'https://cdn.skypack.dev/gsap@3.13.0';
</script>现代项目用 npm,快速试验用 CDN。刚入门的话,CDN 一行代码搞定。
1.6 第一个 GSAP 动画
来看第一个例子。5 行代码,让一个方块飞起来:
<!DOCTYPE html>
<html>
<head><style>
.box {
width: 80px; height: 80px;
background: #6c5ce7;
border-radius: 8px;
}
</style></head>
<body>
<div class="box"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.13.0/gsap.min.js"></script>
<script>
gsap.to('.box', {
x: 300, // 向右移动 300px
duration: 1.5, // 持续 1.5 秒
rotation: 360, // 旋转一圈
scale: 1.5, // 放大到 1.5 倍
ease: 'power2.out'
});
</script>
</body>
</html>拆解这 5 行:
gsap.to()—— 最常用的动画方法,从当前状态过渡到目标状态.box—— 选择器(支持 CSS 选择器、DOM 元素、数组)x: 300—— 对transform: translateX(300px)做动画rotation: 360—— 对transform: rotate(360deg)做动画ease: 'power2.out'—— 缓出效果,开始快、结束慢
GSAP 用 x / y / rotation 这些简写属性而不是直接写 transform。它自动处理 transform 的内部计算,避免了 CSS transform 各组件互相覆盖的问题:你只管说要动什么,GSAP 搞定底层细节。
再看看 CSS Animation 怎么做同样的事
/* CSS 版本——繁琐且不可控 */
.box {
animation: fly 1.5s ease-out forwards;
}
@keyframes fly {
100% {
transform: translateX(300px) rotate(360deg) scale(1.5);
}
}对比:
| 维度 | GSAP | CSS Animation |
|---|---|---|
| 代码量 | 5 行 JS | 6+ 行 CSS + 定义关键帧 |
| 暂停/恢复 | .pause() / .resume() 一行搞定 | 需要操作 animation-play-state |
| 中途修改 | 直接调用 API | 需要重新定义 animation |
| 精确回调 | onComplete / onUpdate 等 | animationend 事件,精度有限 |
| 串联编排 | Timeline 一行搞定 | 需要手动计算 animation-delay |
这就是为什么大量开发者从 CSS 动画转向 GSAP。
把这一节跑一遍:位移与旋转
先确认坐标:x 是相对当前布局位置的变换位移,rotation 使用度。一个 Tween 可以同时更新多个属性,但最终布局位置不因此重新计算。演示中的终点根据容器宽度测量,避免移动端越界。
实验:位移与旋转
GSAP 3.13 / 实验亲手调整参数,观察动画差异。点击开启后再播放,不会自动启动动画。
观察与验证:暂停在 50%,分别比较 none 与 power2.out。旋转圈数相同,但半程角度不同,原因是同一个缓动同时影响位移与旋转。
1.7 GSAP 不仅是 UI 动画
GSAP 不只是"更好用的 CSS 动画库"。它能驱动任何 JavaScript 对象,哪怕跟 DOM 毫无关系:
// 动画驱动任意对象
const gameState = { health: 0 };
gsap.to(gameState, {
health: 100,
duration: 2,
onUpdate: () => {
document.getElementById('health-bar').style.width = gameState.health + '%';
}
});
// 滚动数字效果
const counter = { value: 0 };
gsap.to(counter, {
value: 9999,
duration: 3,
onUpdate: () => {
document.getElementById('count').textContent = Math.round(counter.value);
}
});GSAP 不关心你要动画什么——DOM、Canvas、Three.js 场景、纯数据——它只负责在起止值之间平滑插值。 你给它起点和终点,中间的过程它全包了。
把这一节跑一遍:普通对象补间
目标不一定是 DOM。这里先创建普通对象的 number 字段,Tween 更新原始浮点数,再由 onUpdate 把它格式化为可见数字。显示四舍五入不会改变 Tween 内部值。
实验:普通对象补间
GSAP 3.13 / 实验亲手调整参数,观察动画差异。点击开启后再播放,不会自动启动动画。
观察与验证:把目标改为 2400,定位到 50%。先计算预期原始值,再核对读数。Canvas/WebGL 也是先更新对象,再调用自己的绘制代码。
1.8 GSAP vs 主流框架的协作
GSAP 与框架无关,和所有主流框架都能无缝配合:
// React 中使用
useEffect(() => {
const box = boxRef.current;
gsap.to(box, { x: 200, duration: 1 });
return () => { gsap.killTweensOf(box); }; // cleanup
}, []);
// Vue 中使用
onMounted(() => {
gsap.to('.vue-box', { y: -50, duration: 0.8 });
});
// 原生 JS
document.addEventListener('DOMContentLoaded', () => {
gsap.to('#native-box', { scale: 1.2, duration: 0.5 });
});1.9 常见陷阱
陷阱 1:版本混淆
新手最容易踩的坑——你跟着网上的教程抄代码,结果发现跑不起来,因为教程可能是 2.x 时代的。
// ❌ 2.x 旧写法——GSAP 3 中会报错
TweenMax.to('.box', 1, { x: 100 });
// ✅ GSAP 3.x 正确写法
gsap.to('.box', { x: 100, duration: 1 });GSAP 3 统一了 API:gsap.to() / gsap.from() / gsap.fromTo() / gsap.timeline()。不再有 TweenMax、TweenLite、TimelineMax 的区分。旧教程和 StackOverflow 答案中大量使用旧语法,看到 TweenMax 开头的就要警惕。
陷阱 2:CDN 链接过期
<!-- ❌ 版本号未知或过旧 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
<!-- ✅ 锁定主版本的最新稳定版 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.13.0/gsap.min.js"></script>始终从 cdnjs 或官方文档确认最新版本号。别直接抄别人教程里的链接,那可能已经是好几年前的版本了。
陷阱 3:忘记注册插件
import ScrollTrigger from 'gsap/ScrollTrigger';
// ❌ 忘记注册,ScrollTrigger 不生效
ScrollTrigger.create({ trigger: '.section', start: 'top 80%' });
// ✅ 先注册
gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.create({ trigger: '.section', start: 'top 80%' });就像新电器插上插座但忘了按开关——看起来一切正常,就是不工作。
陷阱 4:误以为 GSAP 是 CSS 动画库
GSAP 的本质是属性插值引擎,CSS 属性只是它能力的一个子集。不要用 CSS 动画的思维来限制它。