放大后如何计算相对于 canvas 的新光标位置?

How can I calculate the new cursor position relative to my canvas after zooming in?

上下文:

我尝试用 Canvas 创建一个着色像素游戏。 截至目前,我通过 strokeRect 渲染了一些可以通过 fillRect.

在点击时绘制的矩形

由于 canvas 不是全屏而是固定大小,因此我需要计算偏移量。当我得到坐标时,我只需将 x 除以矩形宽度 (10)。

这是我的代码。

首先我得到了正确的光标位置:

function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect();

    const x = event.clientX - rect.left
    const y = event.clientY - rect.top

   
    return { x: x, y: y };
  }

然后我将计算 fillRect 的位置,所以看起来我正好在那个位置填充了 strokeRect:

const paint = (e, isClick) => {
    if (!isDrawing && !isClick) {
      return;
    }

    const coordinates = getCursorPosition(canvas, e);

    let rectX = Math.floor(coordinates.x / 10);
    let rectY = Math.floor(coordinates.y / 10);
    // stop drawing when it's outside of the bounds (i have a grid 100 x 100)
    if (rectX > 99 || rectY > 99) {
      return;
    }

    ctx.fillStyle = "black";
    ctx.fillRect(rectX * 10, rectY * 10, 10, 10);
  };

问题:

所以这很有魅力。但是今天我安装了React-zoom-pan-pinch

显然,在我放大 canvas 后,一切都变得一团糟,因为 getCursorPosition 函数必须做更多的工作。我需要在缩放后计算新的正确位置。但是我想不通。

所以在我放大并单击矩形(像素)后,彩色矩形出现在最右边和最底部。所以现在很不受欢迎。

软件包为我提供了这个函数 onZoom,它获取这些参数:ReactZoomPanPinchRefevent。它们有许多属性,例如 xyoffsetX、.. 等等。

我尝试了几种组合,但无法正常工作。

问题:

如何计算相对于 Canvas 的新光标位置,以便在其上绘制矩形?考虑到 onZoom event/props 给我的所有属性,我需要进行什么计算。

以下是此包的所有属性:

https://prc5.github.io/react-zoom-pan-pinch/?path=/story/docs-props--page

不幸的是,我找不到 ReactZoomPanPinchRefevent 给我的道具列表。我可以制作屏幕截图,但列表很长。

到目前为止我发现了什么:

我发现了一个用 react + canvas 制作的 react drawing boar repo。 他使用鼠标滚轮功能,您可以在这里看到:

https://github.com/dilidili/react-drawing-board/blob/master/src/SketchPad.tsx#L858

还有这个矩阵,我可以在这里找到:

https://github.com/dilidili/react-drawing-board/blob/master/src/utils.ts#L4

从没听说过。但也许我需要那样的东西。 react-zoom-pan-pinch 包也在 onZoom 函数中提供了这个参数:

ReactZoomPanPinchRef 上面有这样的状态:

https://imgur.com/a/8t1FpJR

所以我回去试了一下:

 let rectX = Math.floor((coordinates.x + zoomState.offsetX) / rectSize);
    let rectY = Math.floor((coordinates.y + zoomState.offsetY) / rectSize);

现在好多了,但我放大得越远,情况就越糟。

最后但并非最不重要的一点是,这里有一个 codesandbox,您可以在其中尝试所有这些:

https://codesandbox.io/s/dark-darkness-iqwku?file=/src/components/canvas.js:2023-2171

相关文件:index.js + components\canvas.js

如果您需要更多信息,请告诉我。

谢谢大家欣赏。

到目前为止,您似乎一直在摆弄缩放状态的偏移量。然而,偏移量被 canvas.getBoundingClientRect() 完美捕获,因为即使在 CSS 变换之后它仍然是 returns 左上角的位置。

问题出在你转换为rectXrectY:通过放大或缩小你的矩形的大小发生变化,这还没有反映在你的计算中。以下代码段解决了这个问题:

const scale = zoomState?.scale ?? 1;
let rectX = Math.floor(coordinates.x / (rectSize * scale));
let rectY = Math.floor(coordinates.y / (rectSize * scale));

可以在您的 CodeSandbox 的 this fork 中看到一个工作示例。