所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

react gsap动画库使用详解之svg动画

简介

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

评论0

显示验证码
没有账号?注册  忘记密码?