react 如何使用canvas
使用 Canvas 在 React 中的方法
基本用法
在 React 中使用 canvas 需要通过 useRef 或 createRef 获取 DOM 节点。以下是一个简单的示例:
import React, { useRef, useEffect } from 'react';
function CanvasComponent() {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 100);
}, []);
return <canvas ref={canvasRef} width={300} height={300} />;
}
export default CanvasComponent;
动态绘制
可以通过事件或状态变化触发 Canvas 的重新绘制。例如,根据鼠标移动绘制路径:
function InteractiveCanvas() {
const canvasRef = useRef(null);
const [isDrawing, setIsDrawing] = React.useState(false);
const startDrawing = (e) => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(e.nativeEvent.offsetX, e.nativeEvent.offsetY);
setIsDrawing(true);
};
const draw = (e) => {
if (!isDrawing) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.lineTo(e.nativeEvent.offsetX, e.nativeEvent.offsetY);
ctx.stroke();
};
const stopDrawing = () => setIsDrawing(false);
return (
<canvas
ref={canvasRef}
width={500}
height={500}
onMouseDown={startDrawing}
onMouseMove={draw}
onMouseUp={stopDrawing}
onMouseLeave={stopDrawing}
/>
);
}
性能优化
对于复杂的 Canvas 动画或高频更新,建议使用 requestAnimationFrame 实现循环渲染:
function AnimatedCanvas() {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
let frameId;
let x = 0;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 50, 50, 50);
x = (x + 1) % canvas.width;
frameId = requestAnimationFrame(animate);
};
animate();
return () => cancelAnimationFrame(frameId);
}, []);
return <canvas ref={canvasRef} width={300} height={150} />;
}
第三方库集成
如果需要更高级的功能(如图像处理、物理引擎),可以结合第三方库如 fabric.js 或 konva.js:
import React, { useEffect, useRef } from 'react';
import Konva from 'konva';
function KonvaCanvas() {
const containerRef = useRef(null);
useEffect(() => {
const stage = new Konva.Stage({
container: containerRef.current,
width: 300,
height: 300,
});
const layer = new Konva.Layer();
const circle = new Konva.Circle({
x: 150,
y: 150,
radius: 50,
fill: 'green',
});
layer.add(circle);
stage.add(layer);
}, []);
return <div ref={containerRef} />;
}
注意事项
- 避免在每次渲染时重新创建 Canvas 上下文,应通过
useRef持久化引用。 - 清理动画循环时(如
requestAnimationFrame),需在useEffect的返回函数中取消。 - 对于响应式布局,监听窗口大小变化并动态调整 Canvas 的
width和height属性(而非 CSS 缩放)。







