如何解决使用react钩子在画布上绘制矩形
我有一个React + Typescript Web应用程序,我试图在画布上绘制矩形。我想使用React钩子,并尽可能避免使用类。
预期的结果是,当鼠标按下并移动时,可以在画布内绘制所需数量的矩形。另外,我想稍后再扩展它,以允许拖动,调整大小和其他形状。
当前,我能够绘制矩形,但是随着鼠标移动上下文,不断添加矩形来与原始矩形的更新大小相反。
我很少看到与绘制矩形有关的问题,但是我没有使用React钩子看到它们,这就是为什么我决定创建问题。
这是目前正在使用的代码,它可以从上方给出结果。
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,});
};
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,context.canvas.clientWidth,context.canvas.clientHeight),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;
还有codesandbox,您可以在其中查看代码和实际结果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。