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

React中如何让Canvas自适应父容器并随容器尺寸变化?

解决Canvas适配React组件容器并响应尺寸变化的问题

问题分析

你当前的代码存在几个关键问题:

  1. 直接在渲染阶段调用副作用逻辑,不符合React规范;通过document.querySelector('#particles')获取容器可能因DOM未完全挂载失败,还存在重复ID风险
  2. Canvas的width/height属性绑定了窗口尺寸,没有和父容器关联,无法适配两列布局的容器
  3. 未监听容器或窗口尺寸变化,无法响应布局切换或窗口resize

解决方案

重构Particles组件,使用React的useRef获取容器,同步Canvas尺寸与容器,并添加尺寸变化监听:

import { useEffect, useRef } from 'react';

function Particles() {
  const containerRef = useRef(null);
  const canvasRef = useRef(null);

  // 更新Canvas尺寸的函数
  const updateCanvasSize = () => {
    if (!containerRef.current || !canvasRef.current) return;
    const container = containerRef.current;
    const canvas = canvasRef.current;
    
    // 同步Canvas绘制分辨率与容器实际像素尺寸
    canvas.width = container.clientWidth;
    canvas.height = container.clientHeight;
    
    // 这里可重新初始化粒子效果,比如清空画布后重绘
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // ... 你的粒子逻辑代码
  };

  useEffect(() => {
    // 创建Canvas元素
    const canvas = document.createElement('canvas');
    canvas.style.position = 'absolute';
    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.top = 0;
    canvas.style.left = 0;
    canvas.style.zIndex = 0; // 按需调整层级

    // 挂载Canvas到容器
    containerRef.current.appendChild(canvas);
    canvasRef.current = canvas;

    // 初始化尺寸
    updateCanvasSize();

    // 监听窗口resize事件
    window.addEventListener('resize', updateCanvasSize);

    // 清理函数:移除监听和Canvas元素
    return () => {
      window.removeEventListener('resize', updateCanvasSize);
      if (containerRef.current && canvasRef.current) {
        containerRef.current.removeChild(canvasRef.current);
      }
    };
  }, []);

  // 容器设置相对定位,让absolute的Canvas正确填充
  return <div ref={containerRef} className='relative w-full h-full'></div>;
}

export default Particles;

容器代码调整(推荐)

确保承载Particles的容器高度占满,避免Canvas无法填充:

<section className='grid lg:h-[calc(100vh-64px)] lg:max-h-[calc(100vh-64px)] bg-green-400 grid-cols-2 h-full'>
  {/* Main */}
  <section className='bg-blue-300 grid overflow-hidden p-2'>
    <section className='bg-yellow-300 h-full'>
      <Particles />
    </section>
  </section>
  {/* Form */}
  <section className='bg-red-300 grid'>
    <RegisterForm />
  </section>
</section>

关键要点

  • 使用useRef获取容器和Canvas,避免DOM查询的不确定性,符合React组件生命周期规范
  • 区分Canvas的绘制尺寸(width/height属性)和显示尺寸(style的width/height),两者同步才能避免拉伸变形
  • 添加resize事件监听,确保窗口或容器尺寸变化时Canvas能实时适配
  • 清理副作用,防止内存泄漏和DOM残留

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:35:33