简介
gsap 高性能的 JavaScript 动画库,在现代网页设计和开发中运用。
安装
npm install gsap
React 框架中使用
可以考滤使用 react-gsap-enhancer
库,或者 @gasp/react
。
类组件使用 react-gsap-enhancer
高阶组件,函数组件使用 @gasp/react
自定义 Hook。
npm install react-gsap-enhancer
#or
yarn add react-gsap-enhancer
TextPlugin
逐个单词更新
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { TextPlugin } from "gsap/dist/TextPlugin";
gsap.registerPlugin(useGSAP, TextPlugin);
const TextAnimation = () => {
useGSAP(() => {
gsap.to(".gasp-text", {
duration: 2, // 动画持续时间s
text: {
value: "Your new text", // 新文本
delimiter: " ", // 折分文本的字符
newClass: "text-red-500", // 新文本样式
},
});
});
return (
<div>
<h1 className="gasp-text">Hello World!</h1>
</div>
);
};
export default TextAnimation;
ScrambleTextPlugin
解码字符串
使用随机字符(默认大写,但您可以定义小写或一组自定义字符)打乱 DOM 元素中的文本,并定期刷新新的随机字符,同时在补间过程中(默认从左到右)逐渐显示新文本(或原始文本)。视觉上,它看起来像计算机正在解码一串文本。非常适合用于滚动效果。
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrambleTextPlugin } from "gsap/ScrambleTextPlugin";
gsap.registerPlugin(useGSAP, ScrambleTextPlugin);
const TextAnimation = () => {
useGSAP(() => {
gsap.to(".gasp-text", {
duration: 2, // 动画持续时间s
scrambleText: "This is new text",
});
});
return (
<div>
<h1 className="gasp-text">Hello World!</h1>
</div>
);
};
export default TextAnimation;
SplitText
分割文本
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { SplitTextPlugin } from "gsap/SplitTextPlugin";
gsap.registerPlugin(useGSAP, SplitTextPlugin);
const TextAnimation = () => {
useGSAP(() => {
const split = new SplitText(".gasp-text", {
type: "chars",
charsClass: "char",
});
gsap.to(".char", {
duration: 2, // 动画持续时间s
y: 100,
});
});
return (
<div>
<h1 className="gasp-text">Hello World!</h1>
</div>
);
};
export default TextAnimation;
综合示例
目前的示例效果都是单个元素,如果多个元素,按顺序执行的效果处理方式应该如何了?这个就需要使用创建动画时间线方法。
timeline 动画时间线
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP);
const TextAnimation = () => {
useGSAP(() => {
// 设置初始状态
gsap.set([".timeline-1", ".timeline-2", ".timeline-3"], {
opacity: 0,
y: 20,
});
// 创建动画时间线
const tl = gsap.timeline({
defaults: {
duration: 1,
ease: "power2.inOut",
},
});
tl.to(".timeline-1", {
opacity: 1,
y: 0,
stagger: 0.1,
ease: "power2.inOut",
duration: 1,
})
.to(".timeline-2", {
opacity: 1,
y: 0,
stagger: 0.1,
ease: "power2.inOut",
duration: 1,
})
.to(".timeline-3", {
opacity: 1,
y: 0,
stagger: 0.1,
ease: "power2.inOut",
duration: 1,
});
});
return (
<div>
<div className="timeline-1">Join our</div>
<div className="timeline-2">growing</div>
<div className="timeline-3">community</div>
</div>
);
};
export default TextAnimation;
时间线和 SplitText 同时运用
在逐块元素显示的基础上,每块元素并逐个单词显示
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { SplitText } from "gsap/SplitText";
gsap.registerPlugin(useGSAP, SplitText);
const TextAnimation = () => {
useGSAP(() => {
// 创建动画时间线
const tl = gsap.timeline({
defaults: {
duration: 1,
ease: "power2.inOut",
},
});
// 为每个时间线元素创建 SplitText 实例
const split1 = SplitText.create(".timeline-1", { type: "words" });
const split2 = SplitText.create(".timeline-2", { type: "words" });
const split3 = SplitText.create(".timeline-3", { type: "words" });
// 设置分割后的单词初始状态
gsap.set([split1.words, split2.words, split3.words], {
opacity: 0,
y: 20,
});
tl.to(".timeline-1", {
opacity: 1,
y: 0,
duration: 0.5,
onComplete: () => {
gsap.to(split1.words, {
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.5,
});
},
})
.to(".timeline-2", {
opacity: 1,
y: 0,
duration: 0.5,
onComplete: () => {
gsap.to(split2.words, {
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.5,
});
},
})
.to(".timeline-3", {
opacity: 1,
y: 0,
duration: 0.5,
onComplete: () => {
gsap.to(split3.words, {
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.5,
});
},
});
});
return (
<div>
<div className="timeline-1">Join our growing community</div>
<div className="timeline-2">Hello World</div>
<div className="timeline-3">A New Day</div>
</div>
);
};
export default TextAnimation;
以上动画都是页面加载时执行,如果需要做到页面滚动到指定位置时执行,可以使用 ScrollTrigger 插件。
ScrollTrigger 视窗进入离开
import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { SplitText } from "gsap/SplitText";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(useGSAP, SplitText, ScrollTrigger);
const TextAnimation = () => {
useGSAP(() => {
// 为每个时间线元素创建 SplitText 实例
const split1 = SplitText.create(".timeline-1", { type: "words" });
const split2 = SplitText.create(".timeline-2", { type: "words" });
const split3 = SplitText.create(".timeline-3", { type: "words" });
// 设置分割后的单词初始状态
gsap.set([split1.words, split2.words, split3.words], {
opacity: 0,
y: 20,
});
// 设置时间线元素的初始状态
gsap.set([".timeline-1", ".timeline-2", ".timeline-3"], {
opacity: 0,
y: 20,
});
// 创建动画时间线
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".page2",
start: "top 80%", // 当页面顶部到达视窗80%位置时触发
end: "bottom 20%", // 当页面底部到达视窗20%位置时结束
toggleActions: "play none none none", // 只播放一次
markers: true, // 显示触发标记,方便调试
},
});
// play reverse play reverse
// 添加动画序列
tl.to(".timeline-1", {
opacity: 1,
y: 0,
duration: 0.5,
ease: "power2.out",
})
.to(
split1.words,
{
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.3,
ease: "power2.out",
},
"-=0.2"
) // 稍微提前开始单词动画
.to(".timeline-2", {
opacity: 1,
y: 0,
duration: 0.5,
ease: "power2.out",
})
.to(
split2.words,
{
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.3,
ease: "power2.out",
},
"-=0.2"
)
.to(".timeline-3", {
opacity: 1,
y: 0,
duration: 0.5,
ease: "power2.out",
})
.to(
split3.words,
{
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.3,
ease: "power2.out",
},
"-=0.2"
);
});
return (
<div>
<div className="page1 h-[2000px]">高度: 2000px</div>
<div className="page2">
<div className="timeline-1">Join our growing community</div>
<div className="timeline-2">Hello World</div>
<div className="timeline-3">A New Day</div>
</div>
</div>
);
};
export default TextAnimation;
以上代码动画执行一次之后再次进入视窗并不会再次执行. 如果需要重复执行也很简单
const tl = gsap.timeline({
scrollTrigger: {
start: "top bottom-=100", // 当页面顶部到达视窗底部-100px位置时触发
toggleActions: "play none none reverse", // 反复执行
},
});
为了更好的调试,可以开启 markers: true,这样会在浏览器中显示触发标记,更加直观。
const tl = gsap.timeline({
scrollTrigger: {
markers: true, // 显示触发标记,方便调试
},
});
原文链接:https://code.ifrontend.net/archives/332,转载请注明出处。
评论0