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

如何将原生JS实现的波浪线动画转换为React版本?

问题解答

是的,你确实需要用useState和useEffect完成改造,核心原因是React遵循状态驱动UI的理念,要避免直接操作原生DOM,同时要处理组件生命周期里的动画启停逻辑。


改造要点说明

  • 固定不变的横坐标数组xs可以直接提为组件外的常量,避免每次渲染重复生成
  • 每帧都变化的t和动画帧ID用useRef存储,不需要触发组件重渲染,性能远好于放在useState里
  • useState用来存储动态生成的路径d属性,驱动SVG自动更新,不需要手动操作DOM修改属性
  • useEffect用来处理组件挂载时启动动画、卸载时清除动画的逻辑,避免内存泄漏

完整实现代码

import React, { useState, useEffect, useRef } from 'react'

// 固定横坐标,不需要重复生成
const xs = Array.from({ length: 300 }, (_, i) => i)

const WaveAnimation = () => {
  // 存储SVG路径的d属性,驱动UI更新
  const [pathD, setPathD] = useState('')
  // 用useRef存储不需要触发重渲染的可变值
  const tRef = useRef(0)
  const animationIdRef = useRef(null)

  useEffect(() => {
    const animate = () => {
      const points = xs.map(x => {
        const y = 200 + 8 * Math.sin((x + tRef.current) / 5)
        return [x, y]
      })
      const newPath = "M" + points.map(p => `${p[0]},${p[1]}`).join(" L")
      setPathD(newPath)

      tRef.current += 0.5
      animationIdRef.current = requestAnimationFrame(animate)
    }

    // 启动动画
    animate()

    // 组件卸载时清除动画,避免内存泄漏
    return () => {
      cancelAnimationFrame(animationIdRef.current)
    }
  }, [])

  return (
    <div className="Startpage">
      {/* 给svg设置合适的宽高,避免波浪显示不全,可按需调整样式 */}
      <svg width="300" height="400" viewBox="0 0 300 400">
        <path d={pathD} fill="none" stroke="black" strokeWidth="2"/>
      </svg>
    </div>
  )
}

export default WaveAnimation

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:06:02