放大后如何计算相对于 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
,它获取这些参数:ReactZoomPanPinchRef
和 event
。它们有许多属性,例如 x
、y
、offsetX
、.. 等等。
我尝试了几种组合,但无法正常工作。
问题:
如何计算相对于 Canvas 的新光标位置,以便在其上绘制矩形?考虑到 onZoom
event/props 给我的所有属性,我需要进行什么计算。
以下是此包的所有属性:
https://prc5.github.io/react-zoom-pan-pinch/?path=/story/docs-props--page
不幸的是,我找不到 ReactZoomPanPinchRef
和 event
给我的道具列表。我可以制作屏幕截图,但列表很长。
到目前为止我发现了什么:
我发现了一个用 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
上面有这样的状态:
所以我回去试了一下:
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 左上角的位置。
问题出在你转换为rectX
和rectY
:通过放大或缩小你的矩形的大小发生变化,这还没有反映在你的计算中。以下代码段解决了这个问题:
const scale = zoomState?.scale ?? 1;
let rectX = Math.floor(coordinates.x / (rectSize * scale));
let rectY = Math.floor(coordinates.y / (rectSize * scale));
可以在您的 CodeSandbox 的 this fork 中看到一个工作示例。
上下文:
我尝试用 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
,它获取这些参数:ReactZoomPanPinchRef
和 event
。它们有许多属性,例如 x
、y
、offsetX
、.. 等等。
我尝试了几种组合,但无法正常工作。
问题:
如何计算相对于 Canvas 的新光标位置,以便在其上绘制矩形?考虑到 onZoom
event/props 给我的所有属性,我需要进行什么计算。
以下是此包的所有属性:
https://prc5.github.io/react-zoom-pan-pinch/?path=/story/docs-props--page
不幸的是,我找不到 ReactZoomPanPinchRef
和 event
给我的道具列表。我可以制作屏幕截图,但列表很长。
到目前为止我发现了什么:
我发现了一个用 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
上面有这样的状态:
所以我回去试了一下:
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 左上角的位置。
问题出在你转换为rectX
和rectY
:通过放大或缩小你的矩形的大小发生变化,这还没有反映在你的计算中。以下代码段解决了这个问题:
const scale = zoomState?.scale ?? 1;
let rectX = Math.floor(coordinates.x / (rectSize * scale));
let rectY = Math.floor(coordinates.y / (rectSize * scale));
可以在您的 CodeSandbox 的 this fork 中看到一个工作示例。