react 如何使用canvas
使用 Canvas 在 React 中的方法
通过 useRef 直接操作 Canvas
在 React 中可以通过 useRef 获取 Canvas 的 DOM 节点,直接使用 Canvas API 进行绘制。创建一个组件时,在 useEffect 中处理绘制逻辑以避免重复渲染。
import React, { useRef, useEffect } from 'react';
function CanvasComponent() {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
// 绘制矩形
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 100, 100);
}, []);
return <canvas ref={canvasRef} width={300} height={300} />;
}
封装 Canvas 为自定义 Hook
将 Canvas 操作封装为自定义 Hook 以便复用。例如创建一个 useCanvas Hook 处理初始化和绘制逻辑。
function useCanvas(draw) {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
draw(ctx);
}, [draw]);
return canvasRef;
}
function CanvasComponent() {
const draw = (ctx) => {
ctx.fillStyle = 'red';
ctx.fillRect(50, 50, 150, 150);
};
const canvasRef = useCanvas(draw);
return <canvas ref={canvasRef} width={300} height={300} />;
}
动态响应数据变化
通过依赖数组动态更新 Canvas 内容。当传入的数据变化时,触发 useEffect 重新绘制。
function DynamicCanvas({ color, size }) {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = color;
ctx.fillRect(10, 10, size, size);
}, [color, size]);
return <canvas ref={canvasRef} width={300} height={300} />;
}
使用第三方库(如 react-konva)
对于复杂场景(如图层管理、事件处理),可以使用专门为 React 优化的库如 react-konva。
import { Stage, Layer, Rect } from 'react-konva';
function KonvaExample() {
return (
<Stage width={300} height={300}>
<Layer>
<Rect x={20} y={20} width={100} height={100} fill="green" />
</Layer>
</Stage>
);
}
性能优化建议
避免在每次渲染时重新创建绘制函数,使用 useCallback 缓存函数。对于频繁更新的动画,使用 requestAnimationFrame 控制渲染周期。
function AnimatedCanvas() {
const canvasRef = useRef(null);
const frameRef = useRef(0);
const animate = useCallback(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 更新动画逻辑
frameRef.current = requestAnimationFrame(animate);
}, []);
useEffect(() => {
frameRef.current = requestAnimationFrame(animate);
return () => cancelAnimationFrame(frameRef.current);
}, [animate]);
return <canvas ref={canvasRef} width={300} height={300} />;
}
注意事项
- 直接操作 Canvas 时需手动处理清理逻辑(如
clearRect)。 - 在高分辨率屏幕上,通过设置
canvas.width和style.width避免图像模糊。 - 事件监听需通过 React 合成事件系统或直接绑定到 Canvas 节点。







