I got to make "drawing a line" works, but this line wouldn't start from where my mouse starts, rather it'd start from very beginning {x: 0, y:0}. How to draw a line starting from where my mouse clicks?
I already used e.nativeEvent.offsetX and e.nativeEvent.offsetY for getting client X and Y, and this is used for just drawing feature, but I'm stuck how I can utilize it for drawing line, or changing my draw a line code for making it work. Thank you in advanced!
const canvasRef = useRef(null);
const ctxRef = useRef(null);
const [isDrawing, setIsDrawing] = useState(false);
const [lineWidth, setLineWidth] = useState(5);
const [lineColor, setLineColor] = useState("black");
let startPosition = {x: 0, y: 0};
let lineCoordinates = {x: 0, y: 0};
const getClientOffset = (e) => {
const {pageX, pageY} = e.touches ? e.touches[0] : e;
const x = pageX - canvasRef.offsetLeft;
const y = pageY - canvasRef.offsetTop;
return {
x,
y
}
}
const drawLine = () => {
ctxRef.current.beginPath();
ctxRef.current.moveTo(startPosition.x, startPosition.y);
ctxRef.current.lineTo(lineCoordinates.x, lineCoordinates.y);
ctxRef.current.stroke();
}
useLayoutEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.strokeStyle = lineColor;
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctxRef.current = ctx;
}, [lineColor, lineWidth]);
const handleMouseDown = (e) => {
setIsDrawing(true);
// const posX = e.nativeEvent.offsetX;
// const posY = e.nativeEvent.offsetY;
// ctxRef.current.beginPath();
// ctxRef.current.moveTo(
// posX,
// posY
// );
startPosition = getClientOffset(e);
}
const handleMouseMove = (e) => {
if (!isDrawing) {
return;
}
ctxRef.current.lineTo(
e.nativeEvent.offsetX,
e.nativeEvent.offsetY
);
ctxRef.current.stroke();
lineCoordinates = getClientOffset(e);
drawLine();
}
const handleMouseUp = () => {
ctxRef.current.closePath();
setIsDrawing(false);
}
The issue is let startPosition
and let lineCoordinates
– on each render update React will reinitialize these variables with {x: 0, y:0}
. In order to remember any value you must use useState()
.
I tried it out in a demo https://codesandbox.io/s/crazy-breeze-xj26c?file=/src/App.js