什么是CustomBounce
<div class="card">
<h1>案例 34:CustomBounce 弹跳</h1>
<p>根据参数生成弹跳缓动。</p>
<div class="lane">
<div class="ball" id="ball"></div>
</div>
<button id="play">弹跳起来</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/CustomEase.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/CustomBounce.min.js"></script>
<script>
const ball = document.querySelector("#ball");
const playButton = document.querySelector("#play");
// 注册 CustomBounce
gsap.registerPlugin(CustomBounce);
// 生成弹跳缓动
CustomBounce.create("myBounce", {
strength: 0.8,
squash: 0.4,
squashID: "myBounce-squash"
});
const timeline = gsap.timeline({ paused: true });
timeline.to(ball, { y: 90, duration: 1.2, ease: "myBounce" });
timeline.to(ball, { scaleY: 0.7, duration: 1.2, ease: "myBounce-squash" }, 0);
playButton.addEventListener("click", () => {
gsap.set(ball, { y: 0, scaleY: 1 });
timeline.restart();
});
</script>
CustomBounce 是 GSAP(GreenSock Animation Platform) 提供的一个高级插件,用于自动生成逼真、可定制的“弹跳”缓动效果(bounce easing),并同步生成配套的“挤压”(squash)缓动,从而轻松实现物理感十足的弹性动画(如球落地时的弹跳 + 变形)。
📌 简单定义:
CustomBounce能根据你设定的参数(如弹跳强度、挤压程度),自动创建一对缓动函数:
- 一个用于位置弹跳(上下跳动)
- 一个用于形状挤压(落地时压扁、弹起时拉伸)
它解决了传统弹跳动画中“只有上下运动,没有形变”的不真实问题。
✅ 核心功能:
1. 一键生成弹跳缓动
CustomBounce.create("myBounce", {
strength: 0.8, // 弹跳强度(0~1,值越大弹越高、次数越多)
squash: 0.4, // 挤压强度(0~1,值越大落地时越扁)
squashID: "myBounce-squash" // 挤压缓动的名称(自动生成)
});
- 调用后,会注册两个缓动:
"myBounce"→ 用于y位置动画(模拟弹跳轨迹)"myBounce-squash"→ 用于scaleY(或scaleX)动画(模拟挤压变形)
2. 物理感更强
- 弹跳高度逐次衰减(符合能量损耗)
- 挤压发生在每次触地瞬间(时间点精准对齐)
- 无需手动计算关键帧或贝塞尔曲线
🔧 在你的代码中:
// 创建弹跳缓动
CustomBounce.create("myBounce", {
strength: 0.8,
squash: 0.4,
squashID: "myBounce-squash"
});
// 时间轴同步动画
timeline.to(ball, { y: 90, duration: 1.2, ease: "myBounce" }); // 向下弹跳
timeline.to(ball, { scaleY: 0.7, duration: 1.2, ease: "myBounce-squash" }, 0); // 同步挤压
动画效果:
- 小球从顶部下落;
- 触地瞬间垂直压缩(
scaleY变小); - 弹起时恢复原状,并继续多次小幅弹跳;
- 整个过程自然流畅,像真实的橡胶球。
💡 注意:两个动画必须同时开始(
position: 0),才能保证挤压与弹跳同步。
⚙️ 关键参数说明:
| 参数 | 作用 | 推荐范围 |
|---|---|---|
strength | 控制弹跳次数和高度 | 0.1(轻微回弹) ~ 1(剧烈多次弹跳) |
squash | 控制落地时的压缩程度 | 0.1(微扁) ~ 0.6(明显压扁) |
squashID | 指定挤压缓动的名称 | 任意唯一字符串 |
🌟 为什么比普通 bounce 缓动更好?
| 对比项 | CSS / GSAP 内置 bounce | CustomBounce |
|---|---|---|
| 是否有形变 | ❌ 仅有位置变化 | ✅ 同步挤压/拉伸 |
| 可定制性 | ❌ 固定节奏 | ✅ 自由调节强度 |
| 物理真实性 | ⚠️ 生硬、机械 | ✅ 接近真实物体 |
| 开发效率 | 需手动做两个动画 | ✅ 一行代码生成一对缓动 |
🎨 典型应用场景:
- 按钮点击反馈:按下时轻微弹跳+压缩
- 购物车添加商品:商品图标“掉落”进购物车
- 游戏元素:角色跳跃、球类运动
- 加载动画:Logo 弹入
- 数据可视化:柱状图“生长”时带弹跳
⚠️ 注意事项:
- 依赖
CustomEase:必须先引入CustomEase.min.js(因为CustomBounce基于它构建); - 挤压方向:通常用
scaleY模拟垂直弹跳的压缩,水平弹跳可用scaleX; - 初始状态重置:播放前需还原
y和scaleY(如你代码中的gsap.set); - 商业项目需授权:
CustomBounce属于 GSAP Club 会员专属插件(免费试用,商用需订阅)。
📚 官方资源:
✅ 总结:
CustomBounce是 GSAP 中实现“真实弹跳动画”的终极解决方案——它将复杂的物理形变简化为两个同步缓动,让你用极简代码打造出媲美原生应用的生动交互动效。
什么是CustomWiggle
<div class="card">
<h1>案例 35:CustomWiggle 摇摆</h1>
<p>用 CustomWiggle 生成自然的摆动缓动。</p>
<div class="arm">
<div class="stick" id="stick"></div>
</div>
<button id="play">摇一摇</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/CustomEase.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/CustomWiggle.min.js"></script>
<script>
const stick = document.querySelector("#stick");
const playButton = document.querySelector("#play");
// 注册 CustomWiggle
gsap.registerPlugin(CustomWiggle);
// 创建摆动缓动
CustomWiggle.create("myWiggle", {
wiggles: 6,
type: "easeOut"
});
const tween = gsap.to(stick, {
rotation: 40,
duration: 1.4,
ease: "myWiggle",
paused: true
});
playButton.addEventListener("click", () => {
gsap.set(stick, { rotation: 0 });
tween.restart();
});
</script>
CustomWiggle 是 GSAP(GreenSock Animation Platform) 提供的一个高级插件,用于生成自然、可控的“摇摆”或“抖动”缓动效果(wiggle easing)。它能让你的动画在到达目标值的过程中,自动叠加多次平滑的来回摆动,模拟如钟摆、天线晃动、果冻抖动等物理现象。
📌 简单定义:
CustomWiggle会创建一个特殊的缓动函数,使属性值在变化终点附近产生指定次数的衰减式振荡(摇摆),而无需手动编写复杂的关键帧。
它比简单的 repeat + yoyo 更真实、更流畅,且完全集成于 GSAP 动画系统。
✅ 核心功能:
1. 一键生成摇摆缓动
CustomWiggle.create("myWiggle", {
wiggles: 6, // 摆动次数(完整来回算 1 次)
type: "easeOut" // 衰减类型(控制摆动幅度如何减小)
});
- 调用后,注册一个名为
"myWiggle"的缓动函数; - 可直接用于任何 GSAP 动画的
ease属性。
2. 多种衰减模式(type)
| 类型 | 效果 |
|---|---|
"easeOut"(默认) | 摆动幅度快速衰减(最常用) |
"easeInOut" | 先加速后减速,摆动对称 |
"anticipate" | 先反向小幅度“预摆”,再正向摆动(类似弹簧回弹前的拉扯) |
"uniform" | 所有摆动幅度相同(机械感强) |
"random" | 随机幅度和方向(模拟不稳定抖动) |
CustomWiggle.create("myWiggle", {
wiggles: 6,
type: "easeOut"
});
gsap.to(stick, {
rotation: 40, // 从 0° 转到 40°
duration: 1.4,
ease: "myWiggle" // 在接近 40° 时,自动左右摇摆 6 次并逐渐停止
});
动画效果:
- 木棍从垂直位置开始旋转;
- 接近 40° 时,不会直接停住,而是像被风吹动一样:
- 先超过 40° → 回摆到 38° → 再超到 41° → 回摆到 39.5° ……
- 摆动幅度逐次减小,最终稳定在 40°。
💡 这种效果常用于:UI 元素强调、错误提示抖动、卡通角色动作等。
🌟 为什么比手动做更好?
| 方法 | 控制精度 | 代码量 | 自然度 | 可复用性 |
|---|---|---|---|---|
手动写 timeline + 多个 to() | 低 | 高 | 一般 | 差 |
repeat + yoyo | 无法衰减 | 中 | 机械 | 一般 |
CustomWiggle | 高 | 极简 | 逼真 | 优秀 |
⚙️ 常用参数扩展(高级用法):
CustomWiggle.create("jelly", {
wiggles: 8,
type: "easeOut",
strength: 0.7, // 摆动强度(默认 0.5,越大越夸张)
timing: 0.6 // 时间分布(影响摆动节奏)
});
🎨 典型应用场景:
| 场景 | 示例 |
|---|---|
| UI 反馈 | 输入错误时输入框“摇头” |
| 加载指示器 | 图标轻微晃动表示活跃 |
| 游戏角色 | 角色受击后头部晃动 |
| 品牌动画 | Logo 入场带弹性摆动 |
| 数据图表 | 柱状图增长时顶部抖动 |
⚠️ 注意事项:
- 依赖
CustomEase:必须先引入CustomEase.min.js(因为CustomWiggle基于它构建); - 仅作用于数值属性:如
rotation、x、scale、opacity等; - 不适用于颜色或复杂对象;
- 商业项目需授权:
CustomWiggle属于 GSAP Club 会员专属插件(可免费试用,商用需订阅)。
📚 官方资源:
✅ 总结:
CustomWiggle是 GSAP 中实现“生动摇摆动画”的魔法工具——它将复杂的振荡逻辑封装成一行配置,让你轻松赋予界面元素生命力,是打造趣味性与专业感兼备交互动效的秘密武器。
什么是addLabel
<div class="card">
<h1>案例 36:时间线标签与位置</h1>
<p>用 label 和位置参数精准控制动画片段。</p>
<div class="stage">
<div class="box" id="box"></div>
</div>
<div class="controls">
<button id="to-start">跳到 start</button>
<button id="to-mid">跳到 mid</button>
<button class="primary" id="play">播放</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script>
const box = document.querySelector("#box");
const playButton = document.querySelector("#play");
const toStartButton = document.querySelector("#to-start");
const toMidButton = document.querySelector("#to-mid");
// 创建时间线并加入标签
const timeline = gsap.timeline({ paused: true });
timeline.addLabel("start");
timeline.to(box, { x: 200, duration: 0.6, ease: "power2.out" });
timeline.addLabel("mid");
timeline.to(box, { y: -20, duration: 0.4, ease: "power2.out" }, "mid");
timeline.to(box, { x: 420, duration: 0.6, ease: "power2.inOut" }, "mid+=0.2");
timeline.to(box, { y: 0, duration: 0.4 }, ">");
playButton.addEventListener("click", () => {
timeline.restart();
});
toStartButton.addEventListener("click", () => {
timeline.pause().seek("start");
});
toMidButton.addEventListener("click", () => {
timeline.pause().seek("mid");
});
</script>
在 GSAP(GreenSock Animation Platform)中,addLabel() 是 Timeline(时间线) 的一个方法,用于在动画时间轴的特定位置添加一个具名标记(label),就像给视频加书签一样。它让你能用语义化的名称(如 "start"、"explode"、"fade-in")代替精确的时间值(如 1.2 秒),从而更直观、灵活地组织和控制复杂动画序列。
📌 简单定义:
addLabel("name", position)在时间线的某个时刻打上一个“名字标签”,后续可通过这个名称精准跳转、插入动画或同步多个动画片段。
✅ 核心作用:
1. 语义化控制点
不用记“第 1.4 秒发生了什么”,而是用 "mid" 表示“中间状态”。
2. 精准跳转(Seek)
timeline.seek("start"); // 立即跳到 "start" 标签处
timeline.play("mid"); // 从 "mid" 开始播放
3. 作为动画插入的锚点
在构建时间线时,可以用标签名指定新动画的开始时间:
timeline.to(element, { x: 100 }, "mid"); // 与 "mid" 标签同时开始
timeline.to(element, { y: 50 }, "mid+=0.2"); // 在 "mid" 后 0.2 秒开始
const timeline = gsap.timeline({ paused: true });
timeline.addLabel("start"); // 在时间 0 处添加标签 "start"
timeline.to(box, { x: 200, duration: 0.6 });
timeline.addLabel("mid"); // 在当前时间(约 0.6s)处添加标签 "mid"
timeline.to(box, { y: -20, duration: 0.4 }, "mid"); // 与 "mid" 同时开始
timeline.to(box, { x: 420, duration: 0.6 }, "mid+=0.2"); // 在 "mid" 后 0.2s 开始
timeline.to(box, { y: 0, duration: 0.4 }, ">"); // 紧接上一个动画结束
时间线结构可视化:
0s 0.6s 0.6s 0.8s 1.4s 1.8s
│ │ │ │ │ │
├─ start ├─ x→200 ├─ mid ├─ x→420 ├─ y→0 ▶
│ ├─ y→-20 │
│ │ │
└──────────┴──────────┴───────────...
- 点击 “跳到 start” → 盒子回到起点(
x=0, y=0) - 点击 “跳到 mid” → 盒子位于
x=200, y=0(刚完成水平移动,即将向上跳)
⚙️ addLabel() 的完整语法:
timeline.addLabel(labelName, position);
labelName:字符串,如"intro"、"end"position(可选):- 数字:
1.2(1.2 秒处) - 相对位置:
"+=0.5"(当前末尾 +0.5s) - 其他标签:
"start+=1" - 默认:
"+=0"(即当前时间线末尾)
- 数字:
💡 你也可以在
to()/from()等方法中直接定义标签,无需单独调用addLabel:timeline.to(box, { x: 100 }).add("mid") // 等价于 addLabel("mid") // 或更简洁: timeline.to(box, { x: 100, onComplete: () => {} }, "mid"); // 第三个参数是位置
🌟 优势总结:
| 传统方式 | 使用 addLabel() |
|---|---|
timeline.seek(1.2) → 难理解、易出错 | timeline.seek("explosion") → 自解释、易维护 |
| 插入动画需计算时间偏移 | 直接用 "label+=0.3",逻辑清晰 |
| 修改动画时长后,所有时间点需重算 | 标签自动跟随上下文,几乎无需调整 |
🛠️ 实际应用场景:
- 交互式故事:点击按钮跳到“章节2”
- 游戏过场:
"player-jump"、"enemy-appear" - UI 动画:
"menu-open"、"loading-complete" - 调试复杂时间线:快速定位到关键帧
✅ 总结:
addLabel()是 GSAP 时间线的“命名书签”系统——它用人类可读的标签替代冰冷的时间数字,让复杂动画的编排、跳转和维护变得直观、可靠且富有表现力,是专业级交互动画开发的必备技巧。
什么是modifiers
<div class="card">
<h1>案例 37:modifiers 循环取模</h1>
<p>把位移限制在固定范围内,实现循环运动。</p>
<div class="stage">
<div class="dot" id="dot"></div>
</div>
<button id="play">开始循环</button>
<div class="hint">小球会在 0~480 范围内循环</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script>
const dot = document.querySelector("#dot");
const playButton = document.querySelector("#play");
// modifiers 可以在每帧修改数值,这里做取模循环
const tween = gsap.to(dot, {
x: 1200,
duration: 6,
ease: "none",
modifiers: {
x: (value) => `${parseFloat(value) % 480}px`
},
paused: true
});
playButton.addEventListener("click", () => {
tween.restart();
});
</script>
在 GSAP(GreenSock Animation Platform) 中,modifiers 是一个强大的动画配置选项,它允许你在每一帧动画更新时,对目标属性的计算值进行自定义修改,然后再应用到元素上。
你可以把它理解为:“在 GSAP 计算出新值之后、真正设置到元素之前,插入一个自定义的‘过滤器’或‘转换器’。”
📌 简单定义:
modifiers是一个对象,其键是属性名(如x、rotation),值是一个函数。该函数接收 GSAP 计算出的原始值,返回你想要实际应用的值。
modifiers: {
x: (rawValue) => {
// 对 rawValue 做处理,比如取模、限制范围、单位转换等
return processedValue;
}
}
✅ 核心作用:
- 实现循环/回绕效果(如你的案例:0~480 像素内无限循环)
- 限制数值范围(如旋转角度始终在 -180° ~ 180°)
- 单位转换或格式化(如将弧度转角度、数字加单位)
- 创建非线性映射(如对数缩放、自定义曲线)
modifiers: {
x: (value) => `${parseFloat(value) % 480}px`
}
动画过程解析:
- GSAP 正常计算
x从0到1200的线性变化(因为ease: "none"); - 但在每一帧,
modifiers.x函数会被调用:- 接收 GSAP 算出的
value(如500、600、1000...) - 执行
500 % 480 = 20→ 返回"20px" - 元素实际被设置为
transform: translateX(20px)
- 接收 GSAP 算出的
- 结果:小球看似从 0 移动到 480 后瞬间回到 0,形成无缝循环运动。
💡 虽然 GSAP 内部仍在向 1200 推进,但视觉上永远只在
[0, 480)区间内移动。
🌟 其他典型用法示例:
1. 角度循环(-180° ~ 180°)
modifiers: {
rotation: (value) => ((parseFloat(value) + 180) % 360) - 180
}
2. 限制在屏幕内
modifiers: {
x: (value) => Math.min(Math.max(parseFloat(value), 0), window.innerWidth - 50)
}
3. 自定义单位或格式
// 将 scale 值保留两位小数
modifiers: {
scale: (value) => parseFloat(value).toFixed(2)
}
4. 颜色/复杂值?
❌ 注意:
modifiers仅适用于数值型属性(如x,y,rotation,opacity,scale等)。
它不能用于颜色、文本、CSS 字符串等非纯数值属性。
⚠️ 注意事项:
value参数是字符串(如"120px"),通常需用parseFloat()提取数字;- 返回值必须是有效的 CSS 值(如
"120px"、"0.5"、"45deg"); - 性能敏感:函数会在每帧执行,避免 heavy 计算;
- 与
onUpdate的区别:onUpdate是回调通知,不能修改动画值;modifiers是直接干预最终赋值,更底层、更强大。
📚 官方文档:
✅ 总结:
modifiers是 GSAP 中实现“动态值约束”和“循环动画”的利器——它让你在不改变动画逻辑的前提下,通过简单的数学变换(如取模%),创造出无限滚动、角度归一化、边界限制等高级效果,是构建复杂交互动画的秘密武器。
什么是quickSetter
<div class="card">
<h1>案例 38:quickSetter 高频更新</h1>
<p>快速设置属性,适合鼠标跟随。</p>
<div class="stage" id="stage">
<div class="cursor" id="cursor"></div>
</div>
<div class="hint">在区域内移动鼠标</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script>
const stage = document.querySelector("#stage");
const cursor = document.querySelector("#cursor");
// quickSetter 返回高性能的属性设置函数
const setX = gsap.quickSetter(cursor, "x", "px");
const setY = gsap.quickSetter(cursor, "y", "px");
stage.addEventListener("mousemove", (event) => {
const rect = stage.getBoundingClientRect();
const x = event.clientX - rect.left - 20;
const y = event.clientY - rect.top - 20;
setX(x);
setY(y);
});
</script>
quickSetter 是 GSAP(GreenSock Animation Platform) 提供的一个高性能工具函数,用于极速设置元素的 CSS 属性或 transform 值,特别适合需要高频更新的场景(如鼠标跟随、拖拽、游戏循环等)。
📌 简单定义:
gsap.quickSetter(target, property, unit?)返回一个专用函数,该函数能以最高效的方式直接设置目标元素的指定属性值,绕过 GSAP 动画系统的开销。
它不是用来做动画的,而是用来极致优化“即时赋值”性能的。
✅ 为什么需要它?
在普通 JavaScript 中,你可能会这样写鼠标跟随:
// 普通方式(性能较差)
cursor.style.transform = `translate(${x}px, ${y}px)`;
但这种方式存在几个问题:
- 频繁拼接字符串(内存分配 + GC 压力)
- 浏览器需解析整个
transform字符串 - 如果同时设置多个 transform 属性(x/y/rotation/scale),容易互相覆盖
而 quickSetter 解决了这些问题!
🔧 核心优势:
1. 零字符串拼接
内部使用预编译的 setter 函数,直接操作数值,避免字符串操作。
2. 智能处理 transform
- 自动将
x、y、rotation、scale等映射到transform矩阵; - 多个
quickSetter(如x和y)不会互相覆盖,因为 GSAP 内部维护统一的 transform 状态。
3. 自动单位处理
第三个参数指定单位(如 "px"、"deg"),调用时只需传数字:
const setX = gsap.quickSetter(el, "x", "px");
setX(100); // 等价于 el.style.transform += " translateX(100px)"
4. 极致性能
- 比原生
style.transform快 2~5 倍(尤其在高频调用时); - 避免触发不必要的重排(reflow)或样式计算。
const setX = gsap.quickSetter(cursor, "x", "px");
const setY = gsap.quickSetter(cursor, "y", "px");
stage.addEventListener("mousemove", (event) => {
const x = event.clientX - rect.left - 20;
const y = event.clientY - rect.top - 20;
setX(x); // 极速设置 x
setY(y); // 极速设置 y
});
- 鼠标移动时,每帧调用
setX/setY; - 光标元素的
transform被高效更新,无卡顿、无抖动; - 即使快速晃动鼠标,也能保持流畅。
🌟 典型应用场景:
| 场景 | 说明 |
|---|---|
| 自定义光标 | 如你的例子,替代系统光标 |
| 拖拽交互 | 实时更新被拖元素位置 |
| 游戏开发 | 精灵(sprite)位置/旋转高频更新 |
| 粒子系统 | 成百上千个点的位置同步更新 |
| 手势/触控反馈 | 手指移动时实时响应 |
⚙️ 支持的属性(部分):
- Transform 类:
x,y,z,rotation,rotationX,rotationY,scale,scaleX,scaleY,skewX,skewY - CSS 属性:
opacity,backgroundColor,width,height,borderRadius等(但 transform 性能提升最显著)
💡 对于非 transform 属性,
quickSetter仍比直接style.xxx = value更可靠(自动处理单位、兼容性)。
⚠️ 注意事项:
- 不触发动画:
quickSetter只是“设置值”,没有缓动、时间、回调; - 不要用于低频操作:如果只是偶尔更新,用普通方式即可;
- 单位要匹配:比如
rotation应传"deg",x/y传"px"; - 免费可用:
quickSetter是 GSAP 核心 API,无需额外插件或会员。
📚 官方文档:
✅ 总结:
quickSetter是 GSAP 为高性能交互场景提供的“极速通道”——它剥离了动画系统的冗余开销,让你在需要每秒更新数十次甚至上百次的场景中,依然保持丝滑流畅的用户体验,是构建专业级交互动效的底层利器。
什么是matchMedia
<div class="card">
<h1>案例 39:matchMedia 响应式动画</h1>
<p>不同屏幕宽度执行不同动画。</p>
<div class="stage">
<div class="box" id="box"></div>
</div>
<button id="play">播放</button>
<div class="hint">尝试缩放浏览器宽度</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script>
const box = document.querySelector("#box");
const playButton = document.querySelector("#play");
const mm = gsap.matchMedia();
let tween;
// matchMedia 在不同断点创建不同动画
mm.add(
{
desktop: "(min-width: 700px)",
mobile: "(max-width: 699px)"
},
(context) => {
const { desktop } = context.conditions;
tween = gsap.to(box, {
x: desktop ? 460 : 260,
duration: 1.2,
ease: "power2.inOut",
paused: true
});
}
);
playButton.addEventListener("click", () => {
if (tween) {
tween.restart();
}
});
</script>
gsap.matchMedia() 是 GSAP(GreenSock Animation Platform) 提供的一个响应式动画管理工具,用于根据 CSS 媒体查询(media queries) 自动创建、切换或销毁对应的动画,从而实现真正适配不同设备和屏幕尺寸的交互动效。
📌 简单定义:
matchMedia让你用类似 CSS 媒体查询的语法,为桌面端、平板、手机等不同屏幕宽度编写专属动画,并在窗口缩放时自动清理旧动画、启用新动画,避免内存泄漏和逻辑冲突。
它解决了传统响应式动画中“手动监听 resize + 手动 kill 动画”的繁琐与易错问题。
✅ 核心作用:
1. 按屏幕尺寸分发动画
const mm = gsap.matchMedia();
mm.add({
desktop: "(min-width: 700px)",
mobile: "(max-width: 699px)"
}, (context) => {
const { desktop } = context.conditions;
// 根据当前匹配的断点,创建对应动画
tween = gsap.to(box, {
x: desktop ? 460 : 260,
duration: 1.2
});
});
- 当屏幕 ≥700px →
desktop: true→ 移动到x: 460 - 当屏幕 <700px →
mobile: true→ 移动到x: 260
2. 自动生命周期管理
- 当媒体查询从匹配变为不匹配时,GSAP 会自动
kill()掉该上下文中的所有动画; - 当重新匹配时,回调函数重新执行,创建新动画;
- 无需手动监听
window.resize或调用tween.kill()!
3. 支持嵌套与复杂查询
mm.add({
large: "(min-width: 1200px)",
medium: "(min-width: 768px) and (max-width: 1199px)",
small: "(max-width: 767px)"
}, context => { ... });
mm.add(
{
desktop: "(min-width: 700px)",
mobile: "(max-width: 699px)"
},
(context) => {
const { desktop } = context.conditions;
tween = gsap.to(box, {
x: desktop ? 460 : 260,
paused: true
});
}
);
用户操作流程:
- 页面加载时,根据当前窗口宽度选择
desktop或mobile; - 点击“播放” → 执行对应距离的动画;
- 缩放浏览器宽度跨越 700px 临界点 →
- 旧动画自动被销毁;
- 新断点回调触发,创建新
tween(目标位置更新);
- 再次点击“播放” → 使用新目标值动画。
💡 这确保了:无论何时播放,动画总是适配当前屏幕尺寸的。
🌟 优势 vs 手动实现:
| 手动方式 | gsap.matchMedia() |
|---|---|
需 window.addEventListener('resize', ...) | ✅ 自动监听 |
需手动 kill() 旧动画 | ✅ 自动清理 |
| 容易内存泄漏(忘记 kill) | ✅ 安全无泄漏 |
| 代码分散、难维护 | ✅ 集中式声明式管理 |
| 断点逻辑易出错 | ✅ 与 CSS 媒体查询一致 |
⚙️ 高级用法:
返回清理函数(可选)
mm.add("(min-width: 700px)", () => {
const tween = gsap.to(...);
// 可返回一个函数,在上下文失效时调用
return () => {
console.log("桌面端动画已销毁");
};
});
访问原始 MediaQueryList
mm.add("(max-width: 600px)", (context) => {
const { mq } = context; // 原生 MediaQueryList 对象
console.log(mq.matches);
});
⚠️ 注意事项:
- 必须使用 GSAP 3.11.0+(
matchMedia是较新特性); - 回调函数中的动画会被自动收集并管理,无需手动存储;
- 如果动画需要跨断点复用(如只改参数),建议在
matchMedia外创建,内部仅invalidate().restart(); - 免费功能:
matchMedia是 GSAP 核心 API,无需额外插件或会员。
📚 官方文档:
✅ 总结:
gsap.matchMedia()是 GSAP 为现代响应式 Web 设计提供的“智能动画路由器”——它让开发者用声明式语法,轻松实现多端适配的交互动效,并自动处理复杂的生命周期管理,是构建专业级响应式动画的标准方案。
什么是 context
<div class="card" id="scope">
<h1>案例 40:context 与自动清理</h1>
<p>gsap.context() 可以集中创建并一键清理动画。</p>
<div class="stage">
<div class="box" id="box"></div>
</div>
<div class="controls">
<button id="create">创建动画</button>
<button class="primary" id="revert">清理动画</button>
</div>
<div class="hint">点击清理后动画会被移除</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script>
const scope = document.querySelector("#scope");
const createButton = document.querySelector("#create");
const revertButton = document.querySelector("#revert");
let ctx;
createButton.addEventListener("click", () => {
if (ctx) {
ctx.revert();
}
// context 在指定作用域内创建动画,便于统一清理
ctx = gsap.context(() => {
gsap.to("#box", { x: 420, duration: 1.2, ease: "power2.inOut" });
}, scope);
});
revertButton.addEventListener("click", () => {
if (ctx) {
ctx.revert();
}
});
</script>
在 GSAP(GreenSock Animation Platform) 中,gsap.context() 是一个用于组织和管理动画生命周期的工具函数。它的核心作用是:
将一组动画“打包”到一个上下文(context)中,并提供一键还原(revert)的能力,自动清理所有相关动画、恢复元素初始状态。
📌 简单定义:
gsap.context(() => { /* 动画代码 */ }, scope)创建一个受控的动画环境,其中所有通过 GSAP 创建的动画都会被记录下来,后续调用ctx.revert()即可:
- 停止所有动画
- 将元素属性恢复到动画前的原始值
- 释放内存,避免泄漏
这特别适合动态创建/销毁组件、单页应用(SPA)路由切换、模态框打开关闭等场景。
✅ 核心功能解析:
1. 自动收集动画
在 context 回调函数内创建的所有 GSAP 动画(包括 Timeline、Tween、ScrollTrigger 等)都会被自动追踪。
ctx = gsap.context(() => {
gsap.to("#box", { x: 420 }); // 被记录
gsap.timeline().to(".item", { opacity: 0 }); // 被记录
ScrollTrigger.create({ ... }); // 被记录(如果引入了 ScrollTrigger)
});
2. 一键还原(revert())
ctx.revert(); // 执行以下操作:
// - kill 所有动画
// - 将 #box 的 x 恢复为动画前的值(比如 0)
// - 销毁 ScrollTrigger 实例
// - 清理内部引用,防止内存泄漏
💡 关键优势:你不需要手动记住每个
tween或scrollTrigger去kill(),GSAP 全部帮你搞定!
3. 作用域限制(scope 参数)
第二个参数 scope(如你的 #scope 元素)用于:
- 限定选择器的作用范围(类似 jQuery 的
.find()) - 在 React/Vue 等框架中,通常传入当前组件的根 DOM 节点
gsap.context(() => {
gsap.to("button", { scale: 1.2 }); // 只会选中 #scope 内的 button
}, scope); // ← 作用域
ctx = gsap.context(() => {
gsap.to("#box", { x: 420, duration: 1.2 });
}, scope); // scope = .card 元素
- 点击 “创建动画”:
- 如果已有
ctx,先revert()清理旧动画; - 创建新 context,启动盒子移动动画。
- 如果已有
- 点击 “清理动画”:
- 调用
ctx.revert(); - 盒子立即回到原始位置(即使动画正在播放);
- 所有内部状态被重置。
- 调用
✅ 这就是为什么提示说:“点击清理后动画会被移除”——不仅是停止,更是完全回滚。
🌟 典型应用场景:
| 场景 | 说明 |
|---|---|
| React / Vue 组件卸载 | 在 useEffect 或 onUnmounted 中调用 ctx.revert(),防止动画残留 |
| 模态框(Modal)关闭 | 关闭时还原所有入场动画 |
| 页面切换(SPA) | 离开页面时清理 ScrollTrigger 和动画 |
| 动态内容加载 | 加载新内容前清理旧动画,避免冲突 |
React 示例:
useEffect(() => {
const ctx = gsap.context(() => {
gsap.from(".header", { y: -50, opacity: 0 });
}, containerRef);
return () => ctx.revert(); // 组件卸载时自动清理
}, []);
⚠️ 注意事项:
revert()不会删除 DOM 元素,只还原被 GSAP 控制的属性(如x,opacity,backgroundColor等);- 如果元素的初始状态是通过 CSS 设置的,GSAP 会在
context创建时快照原始值,确保能正确还原; - 免费功能:
gsap.context()是 GSAP 3.11+ 的核心 API,无需额外插件或会员; - 多次调用
revert()是安全的(幂等操作)。
📚 官方文档:
✅ 总结:
gsap.context()是 GSAP 提供的“动画沙盒”机制——它让开发者能安全地创建、隔离并一键销毁一组动画,极大简化了复杂应用中的状态管理和内存控制,是现代前端交互动效开发的最佳实践之一。