Reputation: 1792
I have a component that creates a canvas another and another that controls what happens to it on events:
const Parent = () => {
const [canvasRef, zoom, setZoom] = useCanvas();
const onMouseWheel = (e) => {
let tmpZoom = zoom + (e.deltaY / 1000);
setZoom(tmpZoom);
}
return (
<canvas
ref={canvasRef}
width={canvasDimentions.width} // 1080
height={canvasDimentions.height} // 1920
onWheelCapture={onMouseWheel}
/>
);
}
const useCanvas = () => {
const [zoom, setZoom] = useState(1);
const canvasRef = useRef(null);
useEffect(() => {
const canvasObj = canvasRef.current;
const ctx = canvasObj.getContext('2d');
ctx.clearRect(0, 0, canvasDimentions.width * zoom, canvasDimentions.height * zoom); // width * height intial 1920, 1080
console.log(zoom);
ctx.scale(zoom, zoom)
drawSquare(); // draws a simple 100 x 100 square
},[zoom])
return [canvasRef, zoom, setZoom];
}
What's happening whenever I do this is the zoom does get set correctly (the zoom slowly increases in value correctly within my console.log(zoom)
, and decreases when I scroll in the opposite direction.
The strange behaviour I'm getting with ctx.scale(zoom, zoom)
is that let's say I zoom out: (1, 0.9, 0.8 .. etc) and then zoom in the other direction (0.8, 0.9, 1, 1.1 ... etc) it'll keep zooming out instead of zooming the other way (back in), or it will randomly jump to the correct value.
I understand that useState
is asynchronous but if that's the case, how would my console.log of zoom just before passing it scale be correct each and every time?
Upvotes: 0
Views: 416
Reputation: 136608
This has nothing to do with reactjs, that's just how the 2D context scale
method works.
ctx.scale(x, y)
does take the current transformation matrix and multiplies its scaleX
and scaleY
member by x
and y
.
So if you call scale(0.7, 0.7)
then scale(0.8, 0.8)
, even that second call will actually make the context's transform smaller:
At the beginning scaleX and Y are 1
, at the first call they become 0.7
(1 x 0.7), then they become 0.56
(0.7 x 0.8).
Maybe you'd prefer the setTransform
method which sets the transformation matrix absolutely.
Using this method you could just do
ctx.setTransform(zoom, 0, 0, zoom, 0, 0);
and here going from 0.7
to 0.8
would produce your expected result of zooming-in.
Upvotes: 1