react canvas.scale 在设置时似乎表现不正确

react canvas.scale doesn't seem to behaving correctly when being set

我有一个组件可以创建一个 canvas 另一个组件,另一个组件可以控制事件发生在它身上的事情:

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];
}

每当我这样做时发生的事情是缩放设置正确(缩放值在我的 console.log(zoom) 内正确地缓慢增加,当我向相反方向滚动时减小。

我在 ctx.scale(zoom, zoom) 中遇到的奇怪行为是假设我缩小:(1, 0.9, 0.8 .. 等) 然后向另一个方向放大 (0.8, 0.9, 1, 1.1 ...等)它会继续缩小而不是以另一种方式(返回)放大,或者它会随机跳到正确的值。

我知道 useState 是异步的,但如果是这样的话,我的 console.log 缩放比例在通过它之前如何每次都是正确的?

这与 reactjs 无关,这就是 2D 上下文 scale 方法的工作方式。

ctx.scale(x, y) 确实采用当前变换矩阵并将其 scaleXscaleY 成员乘以 xy

因此,如果您先调用 scale(0.7, 0.7),然后再调用 scale(0.8, 0.8),即使第二次调用实际上也会使上下文的变换变小:

一开始scaleXY1,在第一次调用时它们变成了0.7( 1 x 0.7), 然后它们变成 0.56 (0.7 x 0.8).

也许您更喜欢 setTransform 绝对设置变换矩阵的方法。
使用这种方法你可以做到

ctx.setTransform(zoom, 0, 0, zoom, 0, 0);

这里从 0.70.8 会产生您预期的放大结果。