
在很长一段时间里,我与 GSAP 的关系,可以说是"最熟悉的陌生人"。
时常,遇到一些 CSS 难以驾驭的复杂动画,我的第一反应就是打开 GPT,描述我想要的效果,然后将它生成的 CSS 或者 GSAP 代码复制粘贴到项目中。它能用,效果也不错,项目也成功上线了。
但问题很快就来了。当我想对动画进行一些微调,比如"让第二个动画提前 0.2 秒开始",或者"当用户滚动到一半时暂停整个动画序列"时,AI 生成的代码就成了一个"黑箱"。我看不懂其中的逻辑,只能回去修改我的提问(Prompt),然后一次次地"抽奖"。
我意识到,我只是一个代码的"搬运工",而不是一个"创造者"。这种感觉不是很好。
最近,项目不忙,我下定决心,花半天时间彻底搞懂 GSAP。我打开官方文档,耐着性子读完了核心概念。结果令我大吃一惊------如此简单!曾经让我望而生畏的那些复杂动画,其底层逻辑,无非是建立在两三个核心概念之上。
补间动画(Tween)
官网中遇到的第一个核心概念,叫做 Tween(补间动画)。
这个词听起来很专业,但它的思想却很朴素:"让一个东西,从一个状态,变化到另一个状态。"
GSAP 把这个过程封装成了一个极其简单的函数:gsap.to()
。你只需要告诉它两件事:
- 谁? (动画的目标是谁?)
- 变成什么样? (动画的最终状态和参数是什么?)
比如,我以前让 AI 写一个"方块向右移动并旋转"的动画,它可能会给我一段这样的代码。现在,我能清晰地读懂它的含义。
javascript
// 语法: gsap.to(目标, { ...参数 });
gsap.to(".box", {
duration: 1, // 持续 1 秒
x: 300, // x 轴移动 300px
rotation: 360, // 旋转 360 度
});
x
和 rotation
这些都是 GSAP 的简写,它会自动帮你转换为 transform: translateX(300px) rotate(360deg);
,并且处理好了所有浏览器兼容性问题。
除了 to()
,还有两个几乎一样的函数,只是改变了动画的参照方向:
gsap.from()
:从 你给定的状态,运动到它现在的位置。特别适合做入场动画。gsap.fromTo()
:完全自定义,从 A 状态 ,运动到 B 状态。
理解了这三个函数,就等于掌握了 GSAP 的基本"单词"。你可以创造出任何独立的动画效果。
【最小可运行 Demo】
你可以把下面的代码完整复制到一个 HTML 文件中,用浏览器打开,亲眼见证这三个"单词"的威力。
html
<!DOCTYPE html>
<html>
<head>
<style>
body {
padding: 20px;
font-family: sans-serif;
}
.box {
display: block;
width: 80px;
height: 80px;
background-color: #28a745;
margin-top: 20px;
}
</style>
</head>
<body>
<h3>gsap.to (到...)</h3>
<div class="box box1"></div>
<h3>gsap.from (从...)</h3>
<div class="box box2"></div>
<h3>gsap.fromTo (从...到...)</h3>
<div class="box box3"></div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
// Box 1: 动画"到" x:300 的位置
gsap.to(".box1", { x: 300, duration: 1.5 });
// Box 2: "从" x:300 的位置,动画到它当前的位置 (x:0)
gsap.from(".box2", { x: 300, duration: 1.5 });
// Box 3: "从" x:-100 的位置,"到" x:300 的位置
gsap.fromTo(
".box3",
{ x: -100, opacity: 0 },
{ x: 300, opacity: 1, duration: 1.5 }
);
</script>
</body>
</html>
时间线 (Timeline)
假设 Tween 是动画组成的"单词",那么 Timeline (时间线) 就是 GSAP 用来"遣词造句"的语法。
我以前最大的困惑,就是如何组织多个动画。比如,先执行 A,A 结束后再执行 B,B 开始的同时执行 C。之前的代码里总是一堆 delay
(延迟)参数,彼此依赖,改一个就得改全部,非常脆弱。
Timeline 完美地解决了这个问题。
你可以创建一个时间线,然后把你的所有 Tween(补间动画)按顺序放进去。
javascript
// 以前,我可能会看到这样的"延迟地狱"代码
gsap.to(".box1", { x: 200, duration: 1 });
gsap.to(".box2", { y: 100, duration: 0.5, delay: 1 }); // 依赖于第一个动画的时长
gsap.to(".box3", { rotation: 90, duration: 1, delay: 1.5 }); // 依赖于前两个...
// 现在,用时间线,逻辑清晰如画
const tl = gsap.timeline();
tl.to(".box1", { x: 200, duration: 1 });
tl.to(".box2", { y: 100, duration: 0.5 });
tl.to(".box3", { rotation: 90, duration: 1 });
在这段代码里,动画会严格地按照添加顺序一个接一个播放。无论你如何修改某个动画的 duration
,后续的动画总能正确地衔接。
更强大的是,你可以控制动画的"插入点",实现复杂的编排。
javascript
tl.to(".box1", { x: 200, duration: 1 })
.to(".box2", { y: 100, duration: 0.5 }, "-=0.5") // 在上个动画结束前 0.5s 开始
.to(".box3", { rotation: 90, duration: 1 }, "<"); // 和上个动画同时开始
当你了解了 Timeline 之后,过去那些看起来高深莫测的序列动画,都会变得清晰明了。

缓动效果
掌握了 Tween 和 Timeline,已经能构建出任何复杂的动画结构了。剩下的,就是一些让动画更生动、更优雅的微调。
其中有两个是我过去最常用,但不知其所以然的属性。
-
stagger
(交错)场景:让一组元素(比如导航栏的菜单项、文章的标题字母)依次入场。 我以前会告诉 AI:"让它们一个接一个出现"。现在我明白了,只需要一个
stagger
属性。javascript// 让所有的 .dot 元素,以 0.1 秒的间隔,依次从 Y 轴 -20px 的位置下来 gsap.from(".dot", { y: -20, opacity: 0, duration: 0.5, stagger: 0.1, // 核心在这里 });
-
ease
(缓动)它决定了动画的速度曲线,是动画的"灵魂"。与其说是"属性",不如说是一种"感觉"。GSAP 内置了海量的缓动效果,比如
power1
、back
、elastic
、bounce
等。 过去我只会说"让它弹一下",现在我可以精确地选择ease: "back.out(1.7)"
(像被拉开后收回)或者ease: "bounce.out"
(像皮球落地)。GSAP 官方提供了一个非常直观的缓动效果可视化工具,强烈建议去玩一下,感受不同
ease
带来的节奏变化。

写在最后
这次学习 GSAP 的经历,对我触动很大。
当一个 AI 工具被我们视为"黑箱"时,我们能做的,就只有输入和输出;而当我们理解了它的核心思想,它就成了我们思想的延伸,我们才能真正用它去"创造"。
GSAP 的核心思想,就是 Tween(补间) 和 Timeline(时间线)。用 Tween 定义单个动画,用 Timeline 编排它们。如此简单,却又如此强大。
如果你也像曾经的我一样,对某些技术感到既熟悉又陌生,不妨也静下心来,花一点点时间去阅读它的"第一章"。你可能会发现,那扇你以为很高的大门,其实门槛就在脚下。
(完)