简介
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
DrawSVG
执行 SVG 路径的动画。
正方形动画
import { useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { DrawSVGPlugin } from "gsap/DrawSVGPlugin";
gsap.registerPlugin(useGSAP, ScrollTrigger, DrawSVGPlugin);
export default function GaspScrollDemo() {
const pathRef = useRef(null);
useGSAP(() => {
// 创建一个从无到有的绘制动画
gsap.fromTo(
pathRef.current,
{
drawSVG: "0%", // 起始状态:完全不可见
},
{
drawSVG: "100%", // 结束状态:完全可见
duration: 2, // 动画持续2秒
ease: "power1.inOut", // 使用缓动效果
repeat: 0, // 重复次数
yoyo: false, // 来回动画
}
);
}, []);
return (
<div className="w-full">
<svg width="200" height="200" viewBox="0 0 100 100">
<path
ref={pathRef}
d="M 10 10 L 90 10 L 90 90 L 10 90 Z"
fill="none"
stroke="#0ae448"
strokeWidth="2"
/>
</svg>
</div>
);
}
平衡车动画
import { useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { DrawSVGPlugin } from "gsap/DrawSVGPlugin";
gsap.registerPlugin(useGSAP, DrawSVGPlugin);
export default function GaspScrollDemo() {
const scooterRefs = useRef([]);
useGSAP(() => {
const timeline = gsap.timeline();
// 第一步:依次绘制所有路径
scooterRefs.current.forEach((path, index) => {
timeline.fromTo(
path,
{
drawSVG: "0%",
fill: "none",
},
{
drawSVG: "100%",
duration: 1,
delay: 0.01,
ease: "power1.inOut",
},
index === 0 ? 0 : ">"
);
});
// 第二步:所有路径绘制完成后,统一填充颜色
timeline.to(scooterRefs.current, {
fill: (index) => scooterRefs.current[index].getAttribute("data-fill"),
duration: 1,
ease: "power1.inOut",
});
}, []);
return (
<div className="w-full flex items-center justify-center p-8">
<svg
height="512"
viewBox="0 0 512.004 512.004"
width="512"
xmlns="http://www.w3.org/2000/svg"
>
<path
ref={(el) => (scooterRefs.current[0] = el)}
data-fill="#c5e1e6"
d="m175.669 463.803c-8.283 0-15-6.716-15-15 0-53.743-43.723-97.467-97.467-97.467-14.622 0-28.673 3.153-41.762 9.371-7.483 3.555-16.432.371-19.986-7.112-3.555-7.482-.37-16.431 7.113-19.985 17.143-8.143 35.525-12.273 54.635-12.273 70.286 0 127.467 57.182 127.467 127.467 0 8.283-6.714 14.999-15 14.999z"
fill="none"
stroke="#c5e1e6"
strokeWidth="2"
/>
<path
ref={(el) => (scooterRefs.current[1] = el)}
data-fill="#008adf"
d="m442.768 321.476c-63.027 2.945-113.414 51.086-120.563 112.327h-210.801c-8.285 0-15 6.716-15 15s6.715 15 15 15h224.932c8.285 0 15-6.716 15-15 0-52.162 40.777-94.928 92.832-97.36 8.275-.387 14.67-7.408 14.283-15.684-.387-8.275-7.402-14.684-15.683-14.283z"
fill="none"
stroke="#008adf"
strokeWidth="2"
/>
<path
ref={(el) => (scooterRefs.current[2] = el)}
data-fill="#0065a3"
d="m442.768 321.476c-63.027 2.945-113.414 51.086-120.563 112.327h-66.204v30h80.335c8.285 0 15-6.716 15-15 0-52.162 40.777-94.928 92.832-97.36 8.275-.387 14.67-7.408 14.283-15.684-.387-8.275-7.402-14.684-15.683-14.283z"
fill="none"
stroke="#0065a3"
strokeWidth="2"
/>
<path
ref={(el) => (scooterRefs.current[3] = el)}
data-fill="#8db9c4"
d="m448.787 415.604c-7.721 0-14.279-5.923-14.932-13.755l-28.796-345.572c-1.291-15.484-11.852-26.275-20.521-26.275-8.283 0-15-6.716-15-15s6.717-15 15-15c12.9 0 25.295 5.971 34.9 16.811 8.852 9.99 14.361 23.12 15.518 36.972l28.797 345.573c.688 8.256-5.447 15.506-13.703 16.194-.425.035-.847.052-1.263.052z"
fill="none"
stroke="#8db9c4"
strokeWidth="2"
/>
<circle
ref={(el) => (scooterRefs.current[4] = el)}
data-fill="#c5e1e6"
cx="63.203"
cy="448.803"
fill="none"
stroke="#c5e1e6"
strokeWidth="2"
r="48.2"
/>
<path
ref={(el) => (scooterRefs.current[5] = el)}
data-fill="#1d4659"
d="m63.203 512.002c-34.848 0-63.199-28.351-63.199-63.199 0-34.849 28.352-63.199 63.199-63.199 34.85 0 63.201 28.35 63.201 63.199 0 34.848-28.352 63.199-63.201 63.199zm0-96.398c-18.306 0-33.199 14.893-33.199 33.199 0 18.307 14.894 33.199 33.199 33.199 18.307 0 33.201-14.893 33.201-33.199s-14.895-33.199-33.201-33.199z"
fill="none"
stroke="#1d4659"
strokeWidth="2"
/>
<circle
ref={(el) => (scooterRefs.current[6] = el)}
data-fill="#8db9c4"
cx="448.803"
cy="448.803"
fill="none"
stroke="#8db9c4"
strokeWidth="2"
r="48.2"
/>
<g fill="none" stroke="#0e232c" strokeWidth="2">
<path
ref={(el) => (scooterRefs.current[7] = el)}
data-fill="#0e232c"
d="m448.803 512.002c-34.848 0-63.199-28.351-63.199-63.199 0-34.849 28.352-63.199 63.199-63.199 34.85 0 63.201 28.35 63.201 63.199 0 34.848-28.352 63.199-63.201 63.199zm0-96.398c-18.307 0-33.199 14.893-33.199 33.199 0 18.307 14.893 33.199 33.199 33.199 18.307 0 33.201-14.893 33.201-33.199s-14.895-33.199-33.201-33.199z"
/>
<path
ref={(el) => (scooterRefs.current[8] = el)}
data-fill="#0e232c"
d="m352.402.002c-8.283 0-15 6.716-15 15s6.717 15 15 15h32.135v-30h-32.135z"
/>
</g>
</svg>
</div>
);
}
MorphSVGP
MorphSVG 用于将一个 SVG 路径变形为另一个 SVG 路径的插件。它允许你创建平滑的过渡效果,使一个形状变为另一个形状。
圆形过度星形
import { useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { MorphSVGPlugin } from "gsap/MorphSVGPlugin";
gsap.registerPlugin(useGSAP, MorphSVGPlugin);
export default function GaspScrollDemo() {
const shapeRef = useRef(null);
useGSAP(() => {
const timeline = gsap.timeline({
repeat: -1,
yoyo: true,
});
const circlePath =
"M 50 0 C 50 0, 100 0, 100 50 C 100 50, 100 100, 50 100 C 50 100, 0 100, 0 50 C 0 50, 0 0, 50 0 Z";
const starPath =
"M 50 0 C 50 0, 55 20, 61 35 C 61 35, 80 35, 98 35 C 98 35, 70 45, 68 57 C 68 57, 75 75, 79 91 C 79 91, 60 80, 50 70 C 50 70, 40 80, 21 91 C 21 91, 25 75, 32 57 C 32 57, 30 45, 2 35 C 2 35, 20 35, 39 35 C 39 35, 45 20, 50 0 Z";
timeline.to(shapeRef.current, {
duration: 3,
morphSVG: starPath,
ease: "power2.inOut",
});
timeline.to(shapeRef.current, {
duration: 3,
morphSVG: circlePath,
ease: "power2.inOut",
});
}, []);
return (
<div className="w-full h-[300px] flex items-center justify-center">
<svg width="200" height="200" viewBox="0 0 100 100">
<path
ref={shapeRef}
d="M 50 0 C 50 0, 100 0, 100 50 C 100 50, 100 100, 50 100 C 50 100, 0 100, 0 50 C 0 50, 0 0, 50 0 Z"
fill="#4CAF50"
stroke="#2E7D32"
strokeWidth="2"
/>
</svg>
</div>
);
}
MotionPath
MotionPath 用于将一个元素沿着指定的路径移动。它允许你创建复杂的动画效果,使元素沿着指定的路径移动。
圆点沿着运动路径移动
import { useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { MotionPathPlugin } from "gsap/MotionPathPlugin";
gsap.registerPlugin(useGSAP, MotionPathPlugin);
export default function GaspScrollDemo() {
const circleRef = useRef(null);
const pathRef = useRef(null);
useGSAP(() => {
const timeline = gsap.timeline({
repeat: -1,
yoyo: true,
});
timeline.to(circleRef.current, {
duration: 3,
motionPath: {
path: pathRef.current,
autoRotate: true,
alignOrigin: [0.5, 0.5],
curviness: 1,
type: "cubic",
resolution: 100,
align: pathRef.current,
},
ease: "none",
});
}, []);
return (
<div className="w-full h-[300px] flex items-center justify-center">
<svg width="300" height="300" viewBox="0 0 300 300">
{/* 运动路径 */}
<path
ref={pathRef}
d="M 150 50
C 200 50, 250 100, 250 150
C 250 200, 200 250, 150 250
C 100 250, 50 200, 50 150
C 50 100, 100 50, 150 50"
fill="none"
stroke="#ddd"
strokeWidth="2"
/>
{/* 移动的圆点 */}
<circle
ref={circleRef}
r="8"
fill="#FF69B4"
stroke="#FF1493"
strokeWidth="2"
/>
</svg>
</div>
);
}
放大路径动画
import { useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { MotionPathPlugin } from "gsap/MotionPathPlugin";
gsap.registerPlugin(useGSAP, MotionPathPlugin);
export default function GaspScrollDemo() {
const box1Ref = useRef(null);
const box2Ref = useRef(null);
const box3Ref = useRef(null);
const box4Ref = useRef(null);
useGSAP(() => {
const scales = [{ scale: 1.3 }, { scale: 0.2 }, { scale: 1 }];
const boxes = [box1Ref, box2Ref, box3Ref, box4Ref];
boxes.forEach((box, index) => {
const timeline = gsap.timeline({
repeat: -1,
yoyo: true,
});
timeline.to(box.current, {
motionPath: {
path: scales,
curviness: 1,
},
duration: 3,
ease: "none",
repeat: -1,
repeatDelay: 1,
});
});
}, []);
return (
<div className="w-full m-10 flex items-center justify-center gap-8">
<div ref={box1Ref} className="w-10 h-10 bg-green-500"></div>
<div ref={box2Ref} className="w-10 h-10 bg-red-500"></div>
<div ref={box3Ref} className="w-10 h-10 bg-blue-500"></div>
<div ref={box4Ref} className="w-10 h-10 bg-yellow-500"></div>
</div>
);
}
MotionPathHelper
MotionPathHelper 是一个辅助工具,用于在开发过程中可视化运动路径。它可以帮助你更好地理解运动路径的形状和方向,从而更准确地创建动画效果。
gsap.registerPlugin(MotionPathHelper);
MotionPathHelper.create(tween);
原文链接:https://code.ifrontend.net/archives/337,转载请注明出处。
评论0