reactjs - 在 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上的代码。
解决方案
奇怪之处在于被动画的破折号数组的大小。我不认为这是您的意图,而是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
推荐阅读
- javascript - 侧边栏导航 - 单击关闭侧边栏的侧边导航外部
- python - 在变量中加载 JSON 文件时出现“预期表达式”
- c# - Automapper 不适用于嵌套对象
- javascript - 将背景图像添加到 create-react-native 项目
- thingsboard - 如何在 Thingsboard 中使用丰富节点
- oracle - 从 Oracle 数据库导入 XML 数据时 Solr DIH 变慢
- javascript - React 中的多个 API 调用
- neural-network - 使用 PyTorch 初始化权重和偏差 - 如何更正尺寸?
- pandas - 如何以更易读的方式使用 pandas 改变分组数据帧的列?
- javascript - JavaScript/JQuery 中的多表单提交功能?