GSAP
GSAP (GreenSock Animation Platform) 是一个功能强大的 JavaScript 动画库,可以轻松创建高性能、流畅的动画效果。 它适用于网页、应用程序和任何可以运行 JavaScript 的环境。
环境配置
安装
npm install gsap
yarn add gsap
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.7/dist/gsap.min.js"></script>
导入
根据你的项目类型和模块系统,选择相应的导入方式。
import { gsap } from "gsap";
import { gsap } from "gsap/dist/gsap";
<script>
// 当使用 CDN 方式时,gsap 会作为全局变量可用
document.addEventListener("DOMContentLoaded", (event) => {
// gsap 代码在这里!
});
</script>
核心动画方法
GSAP 提供了几种主要的动画方法来创建不同类型的动画效果。
1. to()
方法
to()
方法是最常用的动画方法,它将元素从当前状态动画到指定的目标状态。
<div
class="box1"
style="width: 50px; height: 50px; background: #3b82f6; margin: 20px;"
></div>
document.addEventListener("DOMContentLoaded", () => {
// 将元素从当前位置移动到 x: 200px 的位置
gsap.to(".box1", {
x: 200,
duration: 1,
ease: "power2.out",
});
});
// 基本语法
gsap.to(selector, {
property1: value1,
property2: value2,
duration: timeInSeconds,
ease: easeType,
});
// 示例:将元素移动并改变颜色
gsap.to(".box", {
x: 100, // 水平移动 100px
backgroundColor: "#ff0000", // 改变背景色为红色
duration: 1, // 动画持续 1 秒
ease: "power2.out", // 缓动函数
});
2. from()
方法
from()
方法与 to()
相反,它将元素从指定的初始状态动画到当前状态。
<div class="box2" style="width: 50px; height: 50px; background: #10b981; margin: 20px;"></div>
document.addEventListener('DOMContentLoaded', () => {
// 从 x: -100px 移动到当前位置
gsap.from('.box2', {
x: -100,
opacity: 0,
duration: 1,
ease: 'back.out(1.7)'
});
});
// 基本语法
gsap.from(selector, {
property1: value1,
property2: value2,
duration: timeInSeconds,
ease: easeType,
});
// 示例:从透明和缩放状态恢复
gsap.from(".element", {
opacity: 0, // 初始透明度为 0
scale: 0.8, // 初始缩放为 0.8
duration: 0.8,
ease: "back.out(1.7)",
});
3. fromTo()
方法
fromTo()
方法允许你同时指定动画的起始状态和结束状态,提供了更精确的控制。
<div class="box3" style="width: 50px; height: 50px; background: #f59e0b; margin: 20px;"></div>
document.addEventListener('DOMContentLoaded', () => {
// 从 x: -100px 移动到 x: 100px
gsap.fromTo('.box3',
{x: -100, rotation: 0},
{x: 100, rotation: 360, duration: 1.5, ease: 'power2.inOut'}
);
});
// 基本语法
gsap.fromTo(
selector,
{ fromProperty1: fromValue1, fromProperty2: fromValue2 },
{
toProperty1: toValue1,
toProperty2: toValue2,
duration: timeInSeconds,
ease: easeType,
}
);
// 示例:从特定位置移动到另一特定位置并旋转
gsap.fromTo(
".box",
{ x: -50, rotation: 0 },
{ x: 50, rotation: 360, duration: 1.5, ease: "power2.inOut" }
);
4. set()
方法
set()
方法用于立即设置元素的属性,不产生动画效果,相当于 duration 为 0 的动画。
// 基本语法
gsap.set(selector, {
property1: value1,
property2: value2,
});
// 示例:立即隐藏元素
gsap.set(".element", {
opacity: 0,
x: 100,
});
常用动画属性
GSAP 支持对多种属性进行动画处理,以下是一些最常用的动画属性:
属性类别 | 常用属性 | 描述 | 示例值 |
---|---|---|---|
位置 | x , y | 元素在 x 和 y 轴上的位置 | 100 , -50 |
大小 | width , height , scale , scaleX , scaleY | 元素的尺寸和缩放 | 200 , 0.8 , 1.2 |
旋转 | rotation , rotationX , rotationY | 元素的旋转角度 | 45 , 180 , -90 |
透明度 | opacity | 元素的透明度 | 0 , 0.5 , 1 |
颜色 | color , backgroundColor , borderColor | 元素的颜色属性 | "#ff0000" , "rgba(255,0,0,0.5)" |
样式 | padding , margin , borderRadius , boxShadow | 元素的样式属性 | "10px" , "50%" |
文本 | textShadow , wordSpacing , letterSpacing | 文本相关属性 | "2px 2px 4px rgba(0,0,0,0.5)" |
缓动函数
缓动函数控制动画在其持续时间内的加速度和减速度,使动画看起来更自然。
常用缓动函数
缓动类型 | 描述 | 示例 |
---|---|---|
power1 , power2 , power3 , power4 | 常用的缓动函数,数字越大,效果越明显 | "power2.out" |
back | 有回弹效果的缓动 | "back.out(1.7)" |
elastic | 有弹性效果的缓动 | "elastic.out(1, 0.5)" |
bounce | 有弹跳效果的缓动 | "bounce.out" |
circ | 圆形缓动,常用于平滑的加速/减速 | "circ.inOut" |
expo | 指数级缓动,快速开始或结束 | "expo.out" |
缓动方向
缓动函数通常有三种方向变体:
in
:动画开始时加速out
:动画结束时减速inOut
:动画开始时加速,结束时减速
<div class="ease-container" style="display: flex; gap: 10px; margin: 20px 0;">
<div class="ease-box power1" style="width: 40px; height: 40px; background: #3b82f6;"></div>
<div class="ease-box back" style="width: 40px; height: 40px; background: #10b981;"></div>
<div class="ease-box elastic" style="width: 40px; height: 40px; background: #f59e0b;"></div>
<div class="ease-box bounce" style="width: 40px; height: 40px; background: #ef4444;"></div>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 设置延迟启动,以便观察效果
setTimeout(() => {
gsap.to('.ease-box.power1', {x: 300, duration: 1.5, ease: 'power2.out'});
gsap.to('.ease-box.back', {x: 300, duration: 1.5, ease: 'back.out(1.7)'});
gsap.to('.ease-box.elastic', {x: 300, duration: 1.5, ease: 'elastic.out(1, 0.5)'});
gsap.to('.ease-box.bounce', {x: 300, duration: 1.5, ease: 'bounce.out'});
}, 500);
});
时间线 (Timeline)
时间线是 GSAP 中强大的功能,用于组织和控制多个动画的序列和同步。
创建时间线
// 创建一个基本的时间线
const tl = gsap.timeline();
// 添加动画到时间线
tl.to(".element1", { x: 100, duration: 1 })
.to(".element2", { y: -50, duration: 0.5 })
.to(".element3", { scale: 1.2, duration: 0.8 });
时间线控制方法
方法 | 描述 |
---|---|
tl.play() | 播放时间线 |
tl.pause() | 暂停时间线 |
tl.resume() | 恢复时间线 |
tl.reverse() | 反向播放时间线 |
tl.restart() | 重新开始时间线 |
tl.seek(time) | 跳转到时间线的特定时间点 |
tl.timeScale(scale) | 设置时间线的播放速度 |
时间线配置
// 创建具有配置选项的时间线
const tl = gsap.timeline({
repeat: 2, // 重复 2 次(总共播放 3 次)
repeatDelay: 1, // 重复之间的延迟(秒)
yoyo: true, // 来回播放(如先正向,再反向)
paused: true, // 创建时暂停
});
<div class="timeline-container" style="display: flex; gap: 20px; margin: 20px 0;">
<div class="timeline-box boxA" style="width: 50px; height: 50px; background: #3b82f6;"></div>
<div class="timeline-box boxB" style="width: 50px; height: 50px; background: #10b981;"></div>
<div class="timeline-box boxC" style="width: 50px; height: 50px; background: #f59e0b;"></div>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 创建时间线
const tl = gsap.timeline({
repeat: -1, // 无限重复
repeatDelay: 1,
yoyo: true
});
// 添加动画序列
tl.to('.timeline-box.boxA', {x: 200, duration: 0.8, ease: 'power2.out'})
.to('.timeline-box.boxB', {x: 200, duration: 0.8, ease: 'power2.out'})
.to('.timeline-box.boxC', {x: 200, duration: 0.8, ease: 'power2.out'});
});
选择器
GSAP 支持多种方式来选择要动画的元素:
// CSS 选择器
gsap.to(".class", { x: 100 });
gsap.to("#id", { y: 50 });
gsap.to("div.container > .item", { opacity: 0.5 });
// DOM 元素
gsap.to(document.getElementById("myElement"), { scale: 1.2 });
// DOM 元素数组
const elements = document.querySelectorAll(".items");
gsap.to(elements, { rotation: 45 });
// jQuery 对象(如果使用 jQuery)
gsap.to($(".jquery-element"), { x: 100 });
动画控制方法
除了时间线提供的控制方法外,GSAP 还为单个动画提供了控制方法:
// 创建一个动画并存储引用
const myAnimation = gsap.to(".element", { x: 100, duration: 2, paused: true });
// 控制动画
myAnimation.play(); // 播放动画
myAnimation.pause(); // 暂停动画
myAnimation.resume(); // 恢复动画
myAnimation.reverse(); // 反向播放
myAnimation.restart(); // 重新开始
myAnimation.timeScale(2); // 加速播放(2倍速度)
myAnimation.progress(0.5); // 跳转到动画的 50% 处
myAnimation.kill(); // 终止动画并移除
回调函数
GSAP 提供了多种回调函数,让你可以在动画的不同阶段执行自定义代码:
gsap.to(".element", {
x: 100,
duration: 1,
// 回调函数
onStart: function () {
console.log("动画开始");
},
onUpdate: function () {
console.log("动画更新中,当前进度:" + this.progress());
},
onRepeat: function () {
console.log("动画重复");
},
onComplete: function () {
console.log("动画完成");
},
onReverseComplete: function () {
console.log("反向动画完成");
},
});
实用技巧
1. 批量动画
可以同时为多个元素创建相同的动画:
// 为所有 .item 元素创建动画
gsap.to(".item", {
y: 50,
duration: 0.5,
stagger: 0.1, // 每个元素之间延迟 0.1 秒开始动画
});
2. 相对值动画
可以使用相对值进行动画:
// 相对当前位置移动
gsap.to(".element", {
x: "+=50", // 向右移动 50px
y: "-=30", // 向上移动 30px
});
3. 动画函数值
可以使用函数来计算动态的动画值:
gsap.to(".elements", {
x: function (index, target) {
// 根据元素索引计算不同的 x 值
return index * 50;
},
duration: 0.5,
});
性能优化
使用 CSS 变换:优先使用
x
,y
,scale
,rotation
等 CSS 变换属性,它们性能更好。避免布局抖动:尽量减少动画过程中会触发重排(reflow)的属性,如
width
,height
,margin
,padding
等。使用
will-change
:为频繁动画的元素添加will-change
属性,让浏览器提前优化。
.animated-element {
will-change: transform, opacity;
}
- 使用
kill()
方法:当不再需要某个动画时,使用kill()
方法移除它,释放资源。
插件
GSAP 提供了多种强大的插件,用于扩展核心功能并实现更复杂的动画效果。以下是一些最常用的 GSAP 插件及其使用方法。
1. ScrollTrigger
ScrollTrigger 是 GSAP 最受欢迎的插件之一,它允许你基于滚动位置创建动画。
安装 ScrollTrigger
npm install gsap
yarn add gsap
导入 ScrollTrigger
// ES 模块导入
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
// 注册插件
gsap.registerPlugin(ScrollTrigger);
基本使用
// 基本的滚动触发动画
gsap.to(".element", {
x: 300,
opacity: 1,
scrollTrigger: {
trigger: ".element", // 触发动画的元素
start: "top bottom", // 开始触发的位置(触发元素的顶部与视口底部对齐时)
end: "bottom top", // 结束触发的位置
scrub: true, // 动画进度与滚动位置同步
markers: true, // 显示标记(开发时使用)
},
});
<div class="scroll-trigger-demo" style="height: 400px; overflow-y: scroll; border: 1px solid #ddd; padding: 20px;">
<div style="height: 200px;">向下滚动...</div>
<div class="st-box" style="width: 50px; height: 50px; background: #3b82f6; margin: 20px;"></div>
<div style="height: 800px;">继续滚动...</div>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 注册 ScrollTrigger 插件
if (typeof ScrollTrigger !== 'undefined') {
gsap.registerPlugin(ScrollTrigger);
// 创建滚动触发动画
gsap.to('.st-box', {
x: 300,
backgroundColor: '#10b981',
duration: 1,
scrollTrigger: {
trigger: '.st-box',
start: 'top bottom',
end: 'bottom top',
scrub: true,
containerAnimation: gsap.to('.scroll-trigger-demo', {
scrollTo: 1,
duration: 3,
ease: 'none'
})
}
});
}
});
常用配置选项
选项 | 描述 | 示例值 |
---|---|---|
trigger | 触发动画的元素 | ".my-element" |
start | 开始触发的位置 | "top 80%" , "center center" |
end | 结束触发的位置 | "bottom 20%" , "max" |
scrub | 动画进度与滚动位置同步 | true , 1 (带惯性) |
pin | 固定元素在视图中 | true , ".pin-element" |
markers | 显示触发点标记 | true , {startColor: "green"} |
toggleActions | 定义滚动时的动画行为 | "play pause resume reset" |
2. MotionPath
MotionPath 插件允许元素沿着自定义路径运动,创建复杂的运动轨迹。
安装和导入
// ES 模块导入
import { gsap } from "gsap";
import { MotionPathPlugin } from "gsap/MotionPathPlugin";
// 注册插件
gsap.registerPlugin(MotionPathPlugin);
基本使用
// 创建路径动画
gsap.to(".element", {
motionPath: {
path: ".path-element", // SVG 路径元素或路径数据
align: ".path-element", // 对齐到路径
autoRotate: true, // 自动旋转以匹配路径方向
alignOrigin: [0.5, 0.5], // 对齐原点
},
duration: 3,
repeat: -1,
ease: "linear",
});
<div class="motion-path-container" style="position: relative; height: 200px; margin: 20px 0;">
<!-- SVG 路径 -->
<svg width="100%" height="100%" viewBox="0 0 400 200">
<path d="M50,100 C150,30 250,170 350,100" fill="none" stroke="#e5e7eb" stroke-width="2" />
</svg>
<!-- 运动元素 -->
<div class="mp-box" style="position: absolute; width: 20px; height: 20px; background: #3b82f6; border-radius: 50%; top: 0; left: 0;"></div>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 注册 MotionPath 插件
if (typeof MotionPathPlugin !== 'undefined') {
gsap.registerPlugin(MotionPathPlugin);
// 创建路径动画
gsap.to('.mp-box', {
motionPath: {
path: 'M50,100 C150,30 250,170 350,100',
autoRotate: true,
alignOrigin: [0.5, 0.5]
},
duration: 4,
repeat: -1,
ease: 'linear'
});
}
});
3. Text
Text 插件用于创建文本动画,可以实现字符、单词或行级别的动画效果。
安装和导入
// ES 模块导入
import { gsap } from "gsap";
import { TextPlugin } from "gsap/TextPlugin";
// 注册插件
gsap.registerPlugin(TextPlugin);
基本使用
// 文本打字机效果
gsap.to(".text-element", {
text: "这是一段通过 GSAP Text 插件动画显示的文本",
duration: 2,
ease: "power2.inOut",
});
<div class="text-demo" style="padding: 20px; font-size: 18px;">
<p class="animated-text">正在打字...</p>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 注册 Text 插件
if (typeof TextPlugin !== 'undefined') {
gsap.registerPlugin(TextPlugin);
// 创建文本动画
gsap.to('.animated-text', {
text: "这是一段通过 GSAP Text 插件动画显示的文本",
duration: 2,
ease: "power2.inOut",
repeat: -1,
repeatDelay: 1,
yoyo: true
});
} else {
// 如果插件不可用,显示静态文本
document.querySelector('.animated-text').textContent = "这是一段通过 GSAP Text 插件动画显示的文本";
}
});
4. DrawSVG
DrawSVG 插件用于创建 SVG 路径的绘制动画,非常适合创建描边动画效果。
安装和导入
// ES 模块导入
import { gsap } from "gsap";
import { DrawSVGPlugin } from "gsap/DrawSVGPlugin";
// 注册插件
gsap.registerPlugin(DrawSVGPlugin);
基本使用
// SVG 路径绘制动画
gsap.from("#svg-path", {
drawSVG: "0%", // 从 0% 到 100%
duration: 2,
ease: "power2.inOut",
});
<div class="drawsvg-container" style="padding: 20px;">
<svg width="300" height="200" viewBox="0 0 300 200">
<path id="demo-path" d="M50,100 C100,50 200,150 250,100" fill="none" stroke="#3b82f6" stroke-width="4" />
</svg>
</div>
document.addEventListener('DOMContentLoaded', () => {
// 注册 DrawSVG 插件
if (typeof DrawSVGPlugin !== 'undefined') {
gsap.registerPlugin(DrawSVGPlugin);
// 创建绘制动画
gsap.from('#demo-path', {
drawSVG: '0%',
duration: 2,
repeat: -1,
repeatDelay: 1,
ease: "power2.inOut"
});
}
});
高级特性
1. 变量和动态值
GSAP 允许你在动画中使用变量和动态计算的值,使动画更加灵活。
// 使用变量
// 修复拼写错误:移除多余的 's'
const startX = 0;
const endX = 200;
gsap.to(".element", {
x: endX,
duration: 1,
ease: "power2.out",
});
// 使用函数计算值
gsap.to(".elements", {
rotation: function (index, element) {
return index * 45; // 每个元素旋转角度递增 45 度
},
duration: 0.5,
stagger: 0.1,
});
2. 动画序列和同步
使用时间线,你可以精确控制多个动画的序列和同步。
// 创建动画序列
const tl = gsap.timeline();
tl
// 第一个动画
.to(".box1", { x: 100, duration: 0.5 })
// 第二个动画(与第一个同时开始,有 0.3 秒的重叠)
.to(".box2", { y: -50, duration: 0.5 }, "-=0.3")
// 第三个动画(在前一个动画结束后开始)
.to(".box3", { scale: 1.5, duration: 0.3 })
// 延迟 0.5 秒后开始下一个动画
.to(".all-boxes", { opacity: 0, duration: 0.5 }, "+=0.5");
3. 响应式动画
GSAP 可以与媒体查询结合,创建响应式动画效果。
// 基于窗口宽度创建不同的动画
function createResponsiveAnimation() {
const isMobile = window.innerWidth < 768;
gsap.to(".element", {
x: isMobile ? 50 : 200,
duration: isMobile ? 0.8 : 1.2,
ease: "power2.out",
});
}
// 初始创建动画
createResponsiveAnimation();
// 窗口大小改变时重新创建动画
window.addEventListener("resize", createResponsiveAnimation);
4. 动画分组和控制
你可以将多个动画组合在一起,并统一控制它们。
// 创建动画组
const animations = [
gsap.to(".box1", { x: 100, duration: 1, paused: true }),
gsap.to(".box2", { y: -50, duration: 1, paused: true }),
gsap.to(".box3", { scale: 1.5, duration: 1, paused: true }),
];
// 控制动画组
function playAll() {
animations.forEach((anim) => anim.play());
}
function pauseAll() {
animations.forEach((anim) => anim.pause());
}
function reverseAll() {
animations.forEach((anim) => anim.reverse());
}
GSAP 性能优化
除了前面提到的基本性能优化技巧外,以下是一些更高级的性能优化建议:
1. 使用批量动画
使用单个 tween 或 timeline 来控制多个元素,而不是为每个元素创建单独的动画:
// 不佳的做法:为每个元素创建单独的动画
const elements = document.querySelectorAll(".item");
elements.forEach((el) => {
gsap.to(el, { x: 100, duration: 0.5 });
});
// 更好的做法:使用单个动画控制所有元素
gsap.to(".item", { x: 100, duration: 0.5 });
2. 使用 CSS 变量
结合 CSS 变量使用 GSAP,可以简化动画控制:
.element {
--animation-duration: 1s;
--animation-color: #3b82f6;
transition: all var(--animation-duration) ease;
}
// 使用 GSAP 更新 CSS 变量
gsap.set(":root", {
"--animation-duration": "0.5s",
"--animation-color": "#ef4444",
});
3. 避免不必要的更新
使用 onUpdate
回调时,尽量减少其内部的操作,特别是会导致重排(reflow)的操作:
// 不佳的做法:在 onUpdate 中进行昂贵的 DOM 操作
gsap.to(".element", {
x: 100,
onUpdate: function () {
const value = this.progress() * 100;
document.querySelector(".progress").textContent = Math.round(value) + "%";
},
});
// 更好的做法:使用 requestAnimationFrame 或限制更新频率
let lastUpdate = 0;
gsap.to(".element", {
x: 100,
onUpdate: function () {
const now = Date.now();
if (now - lastUpdate > 16) {
// 大约 60fps
const value = this.progress() * 100;
document.querySelector(".progress").textContent = Math.round(value) + "%";
lastUpdate = now;
}
},
});
4. 使用 will-change
正确
合理使用 will-change
属性,不要过度使用:
/* 不佳的做法:对所有元素使用 will-change */
* {
will-change: transform;
}
/* 更好的做法:只为需要动画的元素使用 */
.animated-element {
will-change: transform, opacity;
}
更新日志
38e56
-于