thu*_*ug_ 5 typescript reactjs react-hooks
我有一个 React+Typescript Web 应用程序,我正在尝试在画布上绘制矩形。我想使用 React hooks 并尽可能避免使用类。
预期结果是当鼠标按下并移动时,能够在画布内绘制所需数量的矩形。我还想稍后扩展它以允许拖动、调整大小和不同的形状。
目前我可以绘制矩形,但是当鼠标移动时,上下文会不断添加矩形,而不是更新原始矩形的大小。
我看到了一些与绘制矩形相关的问题,但是我没有看到任何使用 React hooks 的问题,这就是我决定创建问题的原因。
这是目前正在使用的代码,它给了我上面的结果。
import React, { useEffect, useRef, useState } from 'react';
interface CanvasProps {
width: number;
height: number;
}
type Coordinate = {
x: number;
y: number;
};
type Rectangle = {
start: Coordinate;
completed: boolean;
end?: Coordinate;
};
const Canvas = ({ width, height }: CanvasProps) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [currentMousePosition, setCurrentMousePosition] = useState<Coordinate>({ x: 0, y: 0 });
const [isMouseDown, setMouseDown] = useState(false);
const [activeDrawing, setActiveDrawing] = useState<Rectangle>();
const onMouseMove = (event: MouseEvent) => {
setCurrentMousePosition({
x: event.clientX,
y: event.clientY,
});
};
const triggerMouseDown = (event: MouseEvent) => {
if (!canvasRef.current) return;
let boundingRect = canvasRef.current.getBoundingClientRect();
if (!isMouseDown) {
setMouseDown(true);
//check is there active drawing
if (!activeDrawing)
setActiveDrawing({
start: {
x: event.clientX - boundingRect.left,
y: event.clientY - boundingRect.top,
},
completed: false,
});
}
setCurrentMousePosition({
x: event.clientX - boundingRect.left,
y: event.clientY - boundingRect.top,
});
};
const triggerMouseUp = () => {
setMouseDown(false);
setActiveDrawing(undefined);
draw();
};
const draw = () => {
const canvas: HTMLCanvasElement = canvasRef.current;
const context = canvas.getContext('2d');
if (context && activeDrawing?.start) {
context.putImageData(
context.getImageData(0, 0, context.canvas.clientWidth, context.canvas.clientHeight),
0,
0
);
context.save();
const startX =
currentMousePosition.x < activeDrawing.start.x ? currentMousePosition.x : activeDrawing.start.x;
const startY =
currentMousePosition.y < activeDrawing.start.y ? currentMousePosition.y : activeDrawing.start.y;
const widthX = Math.abs(activeDrawing.start.x - currentMousePosition.x);
const widthY = Math.abs(activeDrawing.start.y - currentMousePosition.y);
// context.beginPath();
console.info('Current Mouse Position', currentMousePosition);
console.info('Active drawing', activeDrawing);
context.rect(startX, startY, widthX, widthY);
context.stroke();
context.restore();
}
};
useEffect(() => {
if (!isMouseDown) return;
if (!canvasRef.current) {
return;
}
draw();
}, [isMouseDown, currentMousePosition]);
useEffect(() => {
if (!canvasRef.current) {
return;
}
const canvas: HTMLCanvasElement = canvasRef.current;
canvas.addEventListener('mouseup', triggerMouseUp);
canvas.addEventListener('mousedown', triggerMouseDown);
canvas.addEventListener('mousemove', onMouseMove);
return () => {
canvas.removeEventListener('mouseup', triggerMouseUp);
canvas.removeEventListener('mouseleave', triggerMouseDown);
canvas.removeEventListener('mousemove', onMouseMove);
};
}, []);
const getCoordinates = (event: MouseEvent): Coordinate | undefined => {
if (!canvasRef.current) {
return;
}
const canvas: HTMLCanvasElement = canvasRef.current;
return { x: event.pageX - canvas.offsetLeft, y: event.pageY - canvas.offsetTop };
};
return <canvas ref={canvasRef} height={height} width={width} />;
};
Canvas.defaultProps = {
width: window.innerWidth,
height: window.innerHeight,
};
export default Canvas;
Run Code Online (Sandbox Code Playgroud)
还有codesandbox,您可以在其中查看代码和实际结果。
小智 1
在你的draw()函数中,尝试添加
context.clearRect(0, 0, canvas.width, canvas.height);
Run Code Online (Sandbox Code Playgroud)
从画布中清除任何不需要的矩形。之后你需要使用
context.beginPath();
Run Code Online (Sandbox Code Playgroud)
如文档中所述:请确保在调用clearRect()之后开始绘制新项目之前调用beginPath()。
完整的draw()函数:
const draw = () => {
const canvas: HTMLCanvasElement = canvasRef.current;
const context = canvas.getContext('2d');
if (context && activeDrawing?.start) {
context.putImageData(
context.getImageData(0, 0, context.canvas.clientWidth, context.canvas.clientHeight),
0,
0
);
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
const startX =
currentMousePosition.x < activeDrawing.start.x ? currentMousePosition.x : activeDrawing.start.x;
const startY =
currentMousePosition.y < activeDrawing.start.y ? currentMousePosition.y : activeDrawing.start.y;
const widthX = Math.abs(activeDrawing.start.x - currentMousePosition.x);
const widthY = Math.abs(activeDrawing.start.y - currentMousePosition.y);
// context.beginPath();
console.info('Current Mouse Position', currentMousePosition);
console.info('Active drawing', activeDrawing);
context.rect(startX, startY, widthX, widthY);
context.stroke();
context.restore();
}
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1806 次 |
最近记录: |