You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现滚动触发SVG绘制动画的问题求助

解决React中滚动绘制SVG动画的问题

核心问题分析

  1. path.getTotalLength is not a function 错误原因:
    • useRef返回的是包含current属性的对象,你直接使用pathRef而非pathRef.current,拿到的不是实际DOM元素。
    • 组件初始化阶段DOM尚未挂载,pathRef.current为null,调用getTotalLength必然报错。
  2. React中事件绑定的正确方式:
    直接在组件顶层添加滚动事件会导致重复绑定,且无法在组件卸载时清理,需用useEffect钩子处理生命周期逻辑。

修改后的代码

import { useRef, useEffect } from "react";

function About() {
  const pathRef = useRef(null);

  useEffect(() => {
    const path = pathRef.current;
    // 确保DOM元素存在再执行逻辑
    if (!path) return;

    // 获取路径总长度并初始化stroke属性
    const pathLength = path.getTotalLength();
    path.style.strokeDasharray = `${pathLength} ${pathLength}`;
    path.style.strokeDashoffset = `${pathLength}`;

    // 滚动事件处理函数
    const handleScroll = () => {
      const scrollTop = document.documentElement.scrollTop + document.body.scrollTop;
      const scrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
      // 避免除以0的情况
      const scrollPercentage = scrollHeight > 0 ? scrollTop / scrollHeight : 0;
      const drawLength = pathLength * scrollPercentage;
      path.style.strokeDashoffset = `${pathLength - drawLength}`;
    };

    // 添加滚动事件监听器
    window.addEventListener("scroll", handleScroll);

    // 组件卸载时移除监听器,防止内存泄漏
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []); // 空依赖数组确保只在组件挂载和卸载时执行

  return (
    <div className="about">
      <div className="about__container">
        <svg
          viewBox="0 0 1043 1831"
          fill="none"
          preserveAspectRatio="xMidYMax meet"
        >
          <path
            ref={pathRef}
            d="M1184.5 3C503.5 3 763 316 595.5 431.5V376.5L645.5 423.5C664.167 436.167 708 446.5 736 426C764.312 405.271 763 402.5 763 402.5C754 390.667 730.4 368 690 368C649.6 368 620.5 409.624 612 418.276L609.5 609H995.5L1.5 1051.5H587.5C590 1059.67 603.3 1076 636.5 1076C638.5 1076 638.667 1074.67 638.5 1074C638.833 1065.33 640.5 1048.2 644.5 1049C649.5 1050 576 1037.5 603 980.5L609.5 971C607.833 961 605.5 941.1 609.5 941.5C613.5 941.9 631.167 950.333 639.5 954.5C651.9 951.3 679.333 952.167 691.5 953C699.667 948.167 716.2 939.1 717 941.5C718 944.5 721 967.5 719 972.5C726 986.5 745.5 1041 681.5 1050C684.5 1049 689.4 1057.8 689 1069L681.5 1440.5C677.5 1793.5 820 1654 1082.5 1654"
            stroke="#0000FF"
            strokeWidth="6"
          />
        </svg>
        <div className="about__landing"></div>
      </div>
    </div>
  );
}

export default About;

关键修改点说明

  • 正确使用Ref:通过pathRef.current获取DOM元素,在useEffect中使用空依赖数组,确保DOM挂载后再执行初始化逻辑。
  • 安全判断:添加if (!path) return,避免DOM元素未加载时执行代码引发错误。
  • 滚动事件管理:在useEffect内定义滚动处理函数,组件卸载时通过返回函数移除监听器,防止内存泄漏。
  • 避免除以0:计算滚动百分比时判断scrollHeight > 0,防止页面高度不足时出现NaN错误。
  • JSX规范:将stroke-width改为React支持的驼峰式strokeWidth,移除SVG内多余的分号。

内容的提问来源于stack exchange,提问作者Omar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:30:45