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

React中Canvas自适应窗口且解决模糊问题的方案咨询

解决React中Canvas清晰且响应窗口resize的问题

要同时解决Canvas模糊和窗口尺寸不响应的问题,核心是结合设备像素比(DPR)处理Canvas分辨率,并监听窗口resize事件实时重绘,具体实现步骤如下:

关键原理

Canvas模糊的根源是其实际像素分辨率与屏幕显示尺寸不匹配(尤其是高DPI屏幕),而resize不响应是因为没有在窗口尺寸变化时重新更新Canvas参数并重绘内容。通过以下两点解决:

  1. 用设备像素比(DPR)计算Canvas的实际宽高,确保分辨率适配屏幕
  2. 监听窗口resize事件,实时更新Canvas尺寸并重绘内容

具体实现代码

1. 封装Canvas组件(Plot.js)

import { useRef, useEffect } from 'react';

const Plot = () => {
  const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const dpr = window.devicePixelRatio || 1;

    // 定义重绘逻辑
    const redraw = () => {
      // 获取Canvas的显示尺寸(flex布局分配的空间)
      const displayWidth = canvas.offsetWidth;
      const displayHeight = canvas.offsetHeight;

      // 设置Canvas实际分辨率:显示尺寸 × 设备像素比
      canvas.width = displayWidth * dpr;
      canvas.height = displayHeight * dpr;

      // 缩放绘图上下文,适配DPR,避免绘图内容变形
      ctx.scale(dpr, dpr);

      // 强制Canvas的显示样式与布局尺寸一致
      canvas.style.width = `${displayWidth}px`;
      canvas.style.height = `${displayHeight}px`;

      // 这里替换为你的自定义绘图逻辑
      ctx.clearRect(0, 0, displayWidth, displayHeight);
      ctx.fillStyle = '#2196F3';
      ctx.fillRect(50, 50, displayWidth - 100, displayHeight - 100);
      ctx.font = '24px sans-serif';
      ctx.fillStyle = '#fff';
      ctx.fillText('清晰且响应resize的Canvas', 60, 80);
    };

    // 初始渲染时执行一次重绘
    redraw();

    // 监听窗口resize事件,实时重绘
    window.addEventListener('resize', redraw);

    // 组件卸载时清理监听
    return () => window.removeEventListener('resize', redraw);
  }, []);

  // flex:1 让Canvas填充父容器剩余空间,display:block消除默认间距
  return <canvas ref={canvasRef} style={{ flex: 1, display: 'block' }} />;
};

export default Plot;

2. 整体布局(App.js)

用flexbox实现顶部栏、右侧侧边栏和Canvas的铺满布局:

import Plot from './Plot';

const App = () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100vh', margin: 0, overflow: 'hidden' }}>
      {/* 顶部栏 */}
      <header style={{ height: '60px', background: '#333', color: '#fff', display: 'flex', alignItems: 'center', padding: '0 20px' }}>
        顶部导航栏
      </header>
      {/* 主内容区:侧边栏 + Canvas */}
      <div style={{ display: 'flex', flex: 1 }}>
        {/* 右侧侧边栏 */}
        <aside style={{ width: '220px', background: '#f5f5f5', padding: '16px' }}>
          右侧侧边栏
        </aside>
        {/* Canvas容器,确保填充剩余空间 */}
        <div style={{ flex: 1, display: 'flex' }}>
          <Plot />
        </div>
      </div>
    </div>
  );
};

export default App;

核心细节说明

  • 设备像素比(DPR):window.devicePixelRatio获取屏幕的像素密度,Canvas实际宽高设置为显示尺寸×DPR,保证内容在高DPI屏幕上清晰无模糊。
  • resize监听:每次窗口尺寸变化时调用redraw函数,重新计算Canvas的显示尺寸和实际分辨率,并重绘内容,确保布局响应式。
  • flex布局配合:Canvas设置flex:1,父容器用flex分配空间,确保Canvas始终填充剩余屏幕区域,无留白或溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:25:24