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

如何将指定JavaScript代码转换为React背景组件?

将Canvas粒子连线动画转为React背景组件

原代码是原生JS实现的Canvas粒子连线动画,转成React组件的核心是利用Hooks管理Canvas元素与动画生命周期,以下是完整实现方案:

完整组件代码

import { useRef, useEffect } from 'react';

const ParticleBackground = () => {
  const canvasRef = useRef(null);
  const animationFrameRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    // 适配窗口尺寸,监听resize动态更新
    const setCanvasSize = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };
    setCanvasSize();
    window.addEventListener('resize', setCanvasSize);

    // 粒子类封装原动画逻辑
    class Particle {
      constructor(x, y, size, color) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.color = color;
        this.speedX = Math.random() * 3 - 1.5;
        this.speedY = Math.random() * 3 - 1.5;
      }
      update() {
        this.x += this.speedX;
        this.y += this.speedY;
        // 边界反弹处理
        if (this.x + this.size > canvas.width || this.x - this.size < 0) {
          this.speedX = -this.speedX;
        }
        if (this.y + this.size > canvas.height || this.y - this.size < 0) {
          this.speedY = -this.speedY;
        }
      }
      draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fillStyle = this.color;
        ctx.fill();
      }
    }

    // 初始化粒子数组
    const particles = [];
    const particleCount = 120;
    for (let i = 0; i < particleCount; i++) {
      const x = Math.random() * canvas.width;
      const y = Math.random() * canvas.height;
      const size = Math.random() * 4 + 1;
      const color = '#ffffff';
      particles.push(new Particle(x, y, size, color));
    }

    // 动画循环:绘制粒子+粒子间连线
    const animate = () => {
      ctx.fillStyle = 'rgba(17, 17, 17, 0.15)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      
      particles.forEach((particle, index) => {
        particle.update();
        particle.draw();
        // 粒子间连线逻辑,距离小于100时绘制连线
        for (let j = index; j < particles.length; j++) {
          const dx = particle.x - particles[j].x;
          const dy = particle.y - particles[j].y;
          const distance = Math.sqrt(dx * dx + dy * dy);
          if (distance < 100) {
            ctx.beginPath();
            ctx.strokeStyle = `rgba(255,255,255,${1 - distance/100})`;
            ctx.lineWidth = 0.3;
            ctx.moveTo(particle.x, particle.y);
            ctx.lineTo(particles[j].x, particles[j].y);
            ctx.stroke();
          }
        }
      });
      animationFrameRef.current = requestAnimationFrame(animate);
    };
    animate();

    // 组件卸载时清理资源,防止内存泄漏
    return () => {
      window.removeEventListener('resize', setCanvasSize);
      cancelAnimationFrame(animationFrameRef.current);
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        zIndex: -1,
        pointerEvents: 'none' // 避免阻挡页面其他元素交互
      }}
    />
  );
};

export default ParticleBackground;

关键细节说明

  • Canvas元素管理:用useRef获取Canvas实例,保证组件渲染时能稳定操作DOM
  • 生命周期控制:在useEffect中初始化动画,返回清理函数移除监听、取消动画帧,避免内存泄漏
  • 背景适配设置:通过inline style将Canvas设为全屏固定定位,z-index: -1保证在页面内容下方,pointerEvents: none不干扰页面交互
  • 逻辑封装:将原全局的粒子逻辑封装为类,所有状态内聚在组件中,避免全局变量污染

使用方式

直接在项目中导入组件并放置在页面根节点即可:

import ParticleBackground from './ParticleBackground';

function App() {
  return (
    <div className="App">
      <ParticleBackground />
      {/* 页面其他业务内容 */}
      <div className="page-content">
        <h1>你的页面标题</h1>
        <p>页面内容区域</p>
      </div>
    </div>
  );
}

如果需要调整动画效果(比如粒子数量、连线距离、颜色),直接修改代码中对应的参数即可。

内容的提问来源于stack exchange,提问作者Raffle.ski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:31:19