首页 > 解决方案 > 在 React 中使用成帧器运动为 svg 文本设置动画

问题描述

我想使用 Framer Motion 在 React 中为 svg 文本的字母轮廓设置动画,这样该行从某个点开始,然后在一段时间内逐渐完成。我有以下示例代码

import { useState, useRef, useEffect } from "react";
import { motion } from "framer-motion";
import "./styles.css";

export default function App() {
  const [letterLength, setLetterLength] = useState(0);
  const letterRef = useRef();

  useEffect(() => {
    setLetterLength(letterRef.current.getTotalLength());
  }, []);

  return (
    <svg
      id="logo"
      width="998"
      height="108"
      viewBox="0 0 998 108"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <mask
        id="path-1-outside-1"
        maskUnits="userSpaceOnUse"
        x="0.867188"
        y="0.21875"
        width="998"
        height="108"
        fill="black"
      >
        <rect fill="white" x="0.867188" y="0.21875" width="998" height="108" />
        <path d="M15.3672 105H1.86719V2.625H15.3672V105Z" />
      </mask>
      <motion.path
        initial={{
          strokeDasharray: letterLength,
          strokeDashoffset: letterLength
        }}
        animate={{
          strokeDasharray: letterLength,
          strokeDashoffset: 0
        }}
        transition={{ duration: 2 }}
        d="M15.3672 105H1.86719V2.625H15.3672V105Z"
        stroke="#EAE3DC"
        strokeWidth="2"
        mask="url(#path-1-outside-1)"
        ref={letterRef}
      />
    </svg>
  );
}

然而,上面的代码表现得很奇怪。在我不想要的预期结果之前,这条线似乎被动画了多次。使用 vanilla JS 和 CSS 为字母设置动画时,我没有这个问题。我认为这个问题与状态变量有关,但我不确定它到底是什么。

这是codesandbox上的代码。

标签: reactjssvgframer-motion

解决方案


奇怪之处在于被动画的破折号数组的大小。我不认为这是您的意图,而是letterLength初始化为 0,然后在第二次渲染时更改为 230。

letterLength我通过设置一个 const 值发现了这一点。

我建议不要在这里搞乱裁判,只使用百分比

      <motion.path
        initial={{
          strokeDasharray: "100%",
          strokeDashoffset: "100%"
        }}
        animate={{
          strokeDashoffset: "0%"
        }}
        transition={{ duration: 2 }}
        d="M15.3672 105H1.86719V2.625H15.3672V105Z"
        stroke="#EAE3DC"
        strokeWidth="2"
        mask="url(#path-1-outside-1)"
      />

像这样:https ://codesandbox.io/s/framer-motion-animate-stroke-with-dasharrayoffset-ezyuj?file=/src/App.js

注意:我还没有找到一种在动画中使用 ref 的好方法,而不仅仅是在 ref 初始化期间隐藏具有不透明度的元素。让我知道如果你发现任何关于这个主题的东西

**当天晚些时候编辑:**

您也可以将 pathLength 设置为 100,以便提前知道长度。

        <motion.path
          // this line is the important part
          pathLength={100}
          initial={{
            strokeDasharray: 100,
            strokeDashoffset: 100
          }}
          animate={{
            strokeDashoffset: 0
          }}
          transition={{ duration: 2 }}
          d="M15.3672 105H1.86719V2.625H15.3672V105Z"
          stroke="#aceca1"
          strokeWidth="2"
          mask="url(#path-1-outside-1)"
        />

谢谢@kirdes https://discordapp.com/channels/341919693348536320/716908973713784904/855851823578218507


推荐阅读