一、 安装:
// npm install gsap 或yarn add gsap
import { gsap } from "gsap";
二、创建Tween
1、Tween(缓动动画):Tween 是执行所有动画工作的东西——可以将其视为高性能的属性设置器。您提供目标(要动画的对象)、持续时间和任何要进行动画的属性,然后当 Tween 的播放头移动到新位置时,它会计算出该点处属性值应该是什么,然后相应地应用它们。
2、创建Tween的方法
(1)、gsap.to:GSAP 会自动计算当前值(您不需要定义起始值,但可以在 fromTo() Tween 中定义)。由于 GSAP 可以动画处理任何对象的任何属性,因此您不受 CSS 属性或 DOM 对象的限制。
// gsap.to(target,vars)
// 在1s内旋转和移动类名为box的元素。x:100相当于:transform:translateX(100px),
gsap.to(".box", {rotation: 27, x: 100, duration: 1});
(2)、gsap.from:将 gsap.from() 视为向后的 Tween,您可以定义值应该从哪里开始,然后它会动画到当前状态,这非常适合将对象动画到屏幕上,因为您可以将它们设置为最终想要它们看起来的样子,然后从其他地方进行动画。例如:
// gsap.from(targets,vars)
// ".box"从opacity:0;和 y:100 ;动画到现在的值
gsap.from(".box", {
opacity: 0,
y: 100,
duration: 1
}
(3)、gsap.fromTo() :可以让您定义动画的起始值和结束值(而不是使用当前状态作为起始或结束的 from() 和 to() Tween)。这非常适合对动画进行完全控制。
// gsap.fromTo(target,fromVars,toVars)
gsap.fromTo(".box", {autoAlpha: 0}, {autoAlpha: 0.5, duration: 1});
3、Timeline:时间轴是一个强大的序列工具,作为缓动和其他时间轴的容器,使得控制它们作为一个整体并精确管理它们的时间变得简单。如果没有时间轴,构建复杂的序列将会更加繁琐,因为您需要为每个动画使用延迟。
// 创建时间轴:
var tl = gsap.timeline();
// 添加动画并序列化
tl.to(".box1", {duration: 2, x: 100})
.to(".box2", {duration: 1, y: 200})
.to(".box3", {duration: 3, rotation: 360});
// 将Tween或Timeline实例分配给变量.就可以随时控制它
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.pause();
addLabel:这个方法是Timeline类的一个方法,它允许您向时间轴添加标签,以便在时间轴上标记重要位置/时间。
// 在相对于标签的位置插入动画实例(官网例子)
var tl2 = gsap.timeline();
tl2.to("#green", {x:750, duration:1})
/*再timeline中添加label,标记重要位置,就可以再其他方法中引用这个label来进行其他操作
如seek("myLabel") or add(myTween, "myLabel") or reverse("myLabel")
*/
// 在timeline结束一秒后添加blueGreenSpin标签
.addLabel("blueGreenSpin", "+=1")
// 在blueGreenSpin标签处添加动画实例
.to("#blue", {x:750, rotation:360, duration:2}, "blueGreenSpin")
// 在blueGreenSpin标签0.5s后插入Tween
.to("#orange", {x:750, rotation:360, duration:2}, "blueGreenSpin+=0.5");
// 还可以通过位置参数精确控制标签位置
// 从timeline开始3s后精确的插入
tl.addLabel("myLabel", 3);
使用pause()、play()、progress()、reverse()、timeScale()等方法可以轻松控制整个序列
Tween和Timeline都扩展了一个Animation类,该类公开了许多有用的方法和属性。以下是一些最常用的方法:
pause()(暂停动画)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.pause();
play()(播放动画)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.play();
progress()(获取或设置动画的进度)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.progress(0.5);
restart()(重新启动动画并头开始播放)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.restart();
resume()(回复播放动画,而不改变其方向)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.pause();
// some time later...
myTween.resume();
reverse()(反转动画的播放方向)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.reverse();
seek()(跳转到特定的时间,而不影响实例是否暂停或反转)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.seek(0.5);
time()(获取或设置播放头(当前时间)的本地位置,不包括任何重复或重复延迟)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.time(0.5);
duration()(允许您获取或设置动画的持续时间,不包括任何重复或重复延迟)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.duration(2);
timeScale()(获取或设置动画的时间缩放比例)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.timeScale(2);
kill()(完全或部分地杀死动画,具体取决于参数)
const myTween = gsap.to(".my-class", {duration: 1, x: 100});
myTween.kill();
三、基本属性
gsap.effects:
gsap.effects是一种可重用的动画代码块,它可以在多个动画序列中使用
注册:
//使用gsap.registerEffect注册effects
// 注册了一个名为fade的effects
gsap.registerEffect({
name: "fade",
extendTimeline: true,
defaults: {duration: 1},
effect: (targets, config) => {
return gsap.to(targets, {opacity: 0, ...config});
}
});
使用:
gsap.effects.fade(".my-class", {duration: 2});
或者,如果您在注册效果时将extendTimeline: true设置为true,则可以像这样使用它:
const myTimeline = gsap.timeline();
myTimeline.fade(".my-class", {duration: 1})
.to(".my-class", {duration: 1, x: 100});
gsap.utils
gsap.utils 提供了一些令人惊讶的有用的实用程序函数。请注意,其中许多函数可以选择返回函数, 以便可以将它们直接插入到缓动中,利用 GSAP 的基于函数的功能。在这种情况下,它们将为每个目标调用一次,而不仅仅是为它们所有人使用相同的结束值。
- 1、checkPrefix():checkPrefix() 函数接受任何 CSS 属性名称,并返回该属性的适当的、浏览器前缀版本(如果需要)。如果不需要前缀,则返回原始属性名称。如果该属性不存在,则返回 undefined。例如:
gsap.utils.checkPrefix("transform"); // "webkitTransform" (on older browsers)
gsap.utils.checkPrefix("transformOrigin"); // "webkitTransformOrigin" (on older browsers)
gsap.utils.checkPrefix("fooBar"); // undefined
- 2、clamp():clamp() 函数将数字限制在给定的最小值和最大值之间。如果您提供的数字小于最小值,则返回最小值。如果它大于最大值,则返回最大值。 如果它在最小值和最大值之间,则返回数字不变。例如:
gsap.utils.clamp(2, 5, 10); // 5
gsap.utils.clamp(12, 5, 10); // 10
gsap.utils.clamp(7, 5, 10); // 7
- 3、distribute():函数返回一个函数,该函数基于您提供的输入来分配值数组
const distribute = gsap.utils.distribute([0, 1, 2, 3, 4]);
const values = distribute(5); // [0, 0.25, 0.5, 0.75, 1]
let distributor = gsap.utils.distribute({
// 开始的值 (默认:0)
base: 50,
// 要在目标之间分配的总量(返回时将此值加上base的值)。因此,如果数量为 100,有 100 个目标,则每个返回值之间将有 1 的差异。
amount: 100,
// 要从目标数组中的哪个位置开始(可以是索引号、关键字(如“start”、“center”、“edges”、“random”或“end”)或沿 x 轴和 y 轴的比率数组,如 [0.25, 0.75])。默认值为 0。
from: "center",
// 基于网格中元素的位置(行、列),如 [5, 10],而不是平坦的数组。您可以使用“auto”来让 GSAP 尝试自动检测 DOM 元素的列和行数。
grid: "auto",
// 对于基于网格的distributing,您可以将测量限制为一个轴(“x”或“y”)
axis: "y",
// 基于缓动曲线进行分配!默认值为“none”。
ease: "power1.inOut"
});
// 获取类名为'.box'元素的数组
let targets = gsap.utils.toArray(".box");
// 现在对于任何目标元素,我们只需从目标数组中输入其索引(连同目标和数组),它就会做所有的计算并返回合适的amount:
let distributedValue = distributor(2, targets[2], targets);
- 4、getUnit(): 函数返回给定字符串的单位,其中数字首先出现,然后是单位。例如:
// 返回css值的单位
gsap.utils.getUnit("50%"); // "%"
gsap.utils.getUnit("100vw"); // "vw"
- 5、interpolate():gsap.utils.interpolate() 是一种超级灵活的方法,可以在任何两个相似类型的值之间线性插值(数字、颜色、字符串、数组、具有多组嵌入数字的复杂字符串、具有多个属性的对象...几乎任何东西!)。
//0和500之间的一半 (number)
gsap.utils.interpolate(0, 500, 0.5); // 250
// strings
gsap.utils.interpolate("20px", "40px", 0.5); // "30px"
//colors
gsap.utils.interpolate("red", "blue", 0.5); // "rgba(128,0,128,1)"
//objects
gsap.utils.interpolate({a:0, b:10, c:"red"}, {a:100, b:20, c:"blue"}, 0.5); // {a: 50, b: 15, c: "rgba(128,0,128,1)"}
// 获得一个可重复使用的函数,根据你以后输入的任何进度值进行插值。
var interp = gsap.utils.interpolate(0, 100);
console.log( interp(0.5) ); // 50
console.log( interp(0.25) ); // 25
console.log( interp(1) ); // 100
// 具有多个属性的对象同样可用
var interp = gsap.utils.interpolate({a:0, b:10, c:"red"}, {a:100, b:20, c:"blue"});
interp(0.5); // {a: 50, b: 15, c: "rgba(128,0,128,1)"}
- 6、mapRange():mapRange()函数将一个数字在一个范围内的相对位置映射到另一个范围中的等效位置。例如,给定0到100的范围,50将是中间位置,因此如果将其映射到0到500的范围,则为250(因为这是该范围的中间位置)
// mapRange(inMin, inMax, outMin, outMax, valueToMap)
// 将-10到10范围内的0映射到100到200范围内的相同位置。
gsap.utils.mapRange(-10, 10, 100, 200, 0); // 150
// 将0-100内的50映射到0-500的相同位置
gsap.utils.mapRange(0, 100, 0, 500, 50); // 250
// 得到一个总是在这些范围之间映射的函数来复用
var mapper = gsap.utils.mapRange(0, 100, 0, 250);
// 复用这个函数映射值
console.log( mapper(50) ); // 125 50在0-100的位置映射到0-250
console.log( mapper(10) ); // 25 10在0-100的位置映射到0-250
- 7、normalize():函数将一个数字在一个范围内的相对位置映射到另一个范围中的等效位置,并将结果限制在0到1之间。它与 mapRange() 相同,但具有硬编码的 outMin/outMax 值为 0/1。例如,如果您有一个范围从0到100的数字,并希望将其映射到0到1之间,则可以使用 utils.normalize()
// in the -10 to 10 range, normalize the number 0 (map it to the corresponding position between 0 and 1)
gsap.utils.normalize(-10, 10, 0); // 0.5
// in the 0 to 100 range, map the number 25
gsap.utils.normalize(0, 100, 25); // 0.25
// 省略 normalize() 函数的第三个参数 valueToNormalize,则该函数将返回一个可重用的函数
var clamper = gsap.utils.normalize(0, 100);
// 复用函数来normalize 0 - 100范围内的值,传的值等于上面的第三个参数
console.log( clamper(50) ); // 0.5
console.log( clamper(10) ); // 0.1
console.log( clamper(75) ); // 0.75
- 8、pipe():函数将多个函数调用串在一起,将一个函数的结果传递给下一个函数。使用 pipe() 函数,您无需手动链接和传递一个函数的返回值到下一个函数的参数中,它可以为您完成这些操作。例如:
// 不用 pipe()
var value1 = func1(input);
var value2 = func2(value1);
var output = func3(value2);
// 或者多层嵌套 (awkward)
var output = func1(func2(func3(input)));
// 你传多少个函数给pipe(),它们就会按照这个顺序被调用,每个函数的返回值都会传给下一个函数。
// 使用 pipe()
var transfrom = gsap.utils.pipe(func1, func2, func3);
var output = transform(input);
- 9、random():获取一个范围内的随机数(可选择四舍五入到你提供的增量),或者一个数组中的随机元素。
// random(minimum, maximum[, snapIncrement, returnFunction]) or random(array[, returnFunction]) or random(minimum, maximum[, returnFunction])
// 获取-100到100之间的随机数 (no snapping)
gsap.utils.random(-100, 100);
// 获取一个在0到500之间的随机数,该随机数被捕捉到最接近5的增量
gsap.utils.random(0, 500, 5);
// get a reusable function that will randomly choose a value between -200 and 500, snapping to an increment of 10
var random = gsap.utils.random(-200, 500, 10, true);
// now we can call it anytime:
console.log( random() ); // random value between -200 and 500, snapping to the closest 10
console.log( random() ); // another random value between -200 and 500, snapping to the closest 10
*/
- 10、selector():获取一个仅限于特定元素的选择器函数,类似于 jQuery 的 .find()
- 11、shuffle():接收一个数组 ,随机的打乱它,返回洗牌后的数组,不会创建一个新的数组。
var array = [1, 2, 3, 4, 5];
gsap.utils.shuffle(array); // 返回同一个数组,但是是重新洗牌后的,如[2, 5, 3, 1, 4]
- 12、snap():捕捉到数组中的某个增量或最接近的值。你可以选择仅在数组中的某个半径/距离值内发生捕捉,包括二维点(具有“x”和“y”属性的对象),并且它将两个维度因素都考虑在半径测量中。
// snap(snapIncrement, valueToSnap)
// 以10的捕捉增量捕捉数字23.5
gsap.utils.snap(10, 23.5); // 20
gsap.utils.snap(2, 9.3); // 10
// snap(snapIncrement)返回一个可复用的函数,接收一个参数(要捕捉的值)
// 获取一个始终捕捉到最接近增量5的倍数函数
var snap = gsap.utils.snap(5);
// now we can reuse the function to snap any values:
console.log( snap(0.5) ); // 0
console.log( snap(4) ); // 5
console.log( snap(21) ); // 20
// snap(array, valueToSnap)
// 找到数组中最接近的值
gsap.utils.snap([100, 50, 500], 65); // 50
gsap.utils.snap([100, 50, 500], 305); // 500
// snap(array)
var snap = gsap.utils.snap([100, 50, 500]); //注意不要传 valueToSnap
// 使用函数获取值
console.log( snap(65) ); // 50
console.log( snap(415) ); // 500
// snap(objectWithRadius, valueToSnap)
// 仅当提供的值位于数组中某个值的半径20以内时,才会发生捕捉
gsap.utils.snap({values:[0, 100, 300], radius:20}, 30.5); // 30.5 (because it's not within 20 of any values)
// 这个会发生snap因为85在半径范围内
gsap.utils.snap({values:[0, 100, 300], radius:20}, 85); // 100
// 也适用于点 (有着"x"和'y"属性的对象):
var point = {x:8, y:8};
gsap.utils.snap({values:[{x:0, y:0}, {x:10, y:10}, {x:20, y:20}], radius:5}, point); // {x:10, y:10}
// 仅当提供的值在从500的任何增量开始的150的半径范围内时才会发生捕捉
gsap.utils.snap({increment: 500, radius: 150}, 975); // 1000 (因为它在500的增量的150以内)
// snap(objectWithRadius)
// 获取一个可重复使用的函数,该函数只有在提供的值位于数组中某个值的半径20以内时才会捕捉
var snap = gsap.utils.snap({values:[0, 100, 300], radius:20}); // notice we didn't provide a valueToSnap
// 使用这个函数来获取值
console.log( snap(50) ); // 50 (不在半径范围内)
console.log( snap(86) ); // 100 (在半径范围内)
console.log( snap(315) ); // 300 (在半径范围内)
- 13、splitColor():将字符串颜色值转换为由[red, green, blue]组成的数组(如果需要alpha值,则在4元素数组的最后一个位置)。例如,[255, 0, 128, 1]。您还可以选择使用第二个参数请求HSLA(色相,饱和度,亮度和alpha)值。eg:
gsap.utils.splitColor("red"); // [255, 0, 0]
gsap.utils.splitColor("#6fb936"); // [111, 185, 54]
gsap.utils.splitColor("rgba(204, 153, 51, 0.5)"); // [204, 153, 51, 0.5]
// 如果需要HSLA值,可以使用第二个参数
gsap.utils.splitColor("#6fb936", true); // [94, 55, 47]
- 14、toArray():将选择器文本、对象数组或选择器文本、NodeList、对象或几乎任何类数组的对象转换为平面数组。您可以选择定义一个范围(在3.7.0中添加)来限制结果为该范围元素的后代,类似于jQuery.find()。eg:
// 这些都返回封装在平面数组中的相应元素:
//选择器文本(返回数组中的原始元素)
let targets = gsap.utils.toArray(".class"); // [div.class]
// 原始 element/object
let targets = gsap.utils.toArray(myElement);
// jQuery (或其他类数组) 对象
let targets = gsap.utils.toArray($(".class"));
// 数组文本选择器 (和".class1, .class2"一样)
let targets = gsap.utils.toArray([".class1", ".class2"]);
// myElement的后代元素
let targets = gsap.utils.toArray(".class", myElement); // [div.class]
- 15、unitize():用于将数字值和字符串连接起来,通常用于 CSS 属性中,以生成带有单位的值。
这个函数的作用是接收两个参数:第一个是数字值,第二个是字符串,最终返回一个字符串。如果第二个参数为 "" 或者是 null,则返回第一个参数的字符串形式;否则会将第一个参数和第二个参数连接起来,生成一个带有单位的字符串。如果第二个参数就已经包含了合法的单位(如 "px"),则直接返回第二个参数的字符串形式。。
// 获取一个给结果加上'px'的函数 (从输入中去除单位)
var clamp = gsap.utils.unitize( gsap.utils.clamp(0, 100), "px");
// 现在结果中就有'px'
clamp(132); // "100px"
clamp("-20%"); // "0px" (注意单位变了)
clamp(50); // "50px"
// 或者使用输入中的任何单位:
var wrap = gsap.utils.unitize( gsap.utils.wrap(0, 100) ); // 在 unitize()中没有明确声明单位
wrap("150px"); // 50px
wrap("130%"); // 30%
// 另一个强制使用“%”这样的单位的例子:
var map = gsap.utils.unitize( gsap.utils.mapRange(-10, 10, 0, 100), "%");
map(0); // 50%
map("5px"); // 75%
// 在modifier 函数中使用:
gsap.to(".class", {
x: 1000,
modifiers: {
//传递给这个函数的值将具有单位,这个函数将去掉单位,以便将原始数字提供给wrap()函数,然后将“px”添加到结果中。
x: gsap.utils.unitize( gsap.utils.wrap(0, window.innerWidth), "px")
}
});
- 16、 wrap():用于对数字或数组索引进行限定范围的处理。当输入的值超出指定范围时,它会将其重新映射到指定范围内。
这个函数可以接收三个参数:第一个参数为需要处理的数字或数组索引,第二个参数为范围的最小值,第三个参数为范围的最大值。当输入的值小于最小值时,gsap.utils.wrap() 会将其重新映射到最大值处;当输入的值大于最大值时,它会将其重新映射到最小值处。这种处理方式类似于循环,经常被用于动画过程中对数值或序列的处理。
//返回数组中的相应值(必要时回到起点)。
let color = gsap.utils.wrap(["red", "green", "yellow"], 5); // "yellow" (索引值5映射到3个元素数组中的2)
//或使用一个区间
let num = gsap.utils.wrap(5, 10, 12); // 7 (12比最大的10多出两个,所以它绕到了起点,并从那里往上走两个。)
//如果我们不提供索引,我们会得到一个准备做相应包装的函数
let wrapper = gsap.utils.wrap(["red", "green", "yellow"]);
//现在我们只需将一个索引值输入到我们从上面一行得到的函数中,我们将从包裹的数组中得到相应的值
let color = wrapper(5) // "yellow"
- 17、wrapYoyo():返回数组中与所提供的索引相关的元素或所提供的范围内的数字,一旦达到最后一个索引,就向后退去(yoyo-ing)(与wrap()不同,wrap是回到起点)。如果没有提供要包装的值,它将返回一个可重用的函数,当它被输入一个值时,它将进行相应的包装。
//返回数组中的相应值(必要时回到开头)。
let color = gsap.utils.wrapYoyo(["red", "green", "yellow"], 5); // "red" (索引5映射到3元素数组中的索引0)
//或使用一个区间
let num = gsap.utils.wrapYoyo(5, 10, 12); // 8 (12 is two past the max of 10, thus the yoyo would go backward to 8)
//12是超过10的最大值的2,因此yoyo会向后走到8。
let wrap = gsap.utils.wrapYoyo(["red", "green", "yellow"]);
//现在我们只需将一个索引号输入到我们从上面一行得到的函数中,我们将从包裹的数组中得到相应的值
let color = wrap(5) // "green"