Javascript 使鼠标坐标相对于<;帆布>;协调

Javascript 使鼠标坐标相对于<;帆布>;协调,javascript,html,canvas,webgl,Javascript,Html,Canvas,Webgl,我试图找到鼠标在画布“网格”上的位置,同时保持大小可调。我现在有鼠标在屏幕上的坐标(x和y) 问题是,WebGL(我正在画布上绘制)和鼠标坐标之间的“缩放”是不同的。WebGL认为从原点向右的10个单位实际上被认为是距离原点的x个单位数(不同的屏幕分辨率会改变这一点)。这意味着当我的鼠标位于WebGL所考虑的(10,10)上方时,我的鼠标坐标为(100100) 如何将屏幕上的鼠标坐标转换为用于定义点的“WebGL坐标” 这与类似,但我不想使用Fabric.js。如果事件侦听器位于canvas元素

我试图找到鼠标在画布“网格”上的位置,同时保持大小可调。我现在有鼠标在屏幕上的坐标(x和y)

问题是,WebGL(我正在画布上绘制)和鼠标坐标之间的“缩放”是不同的。WebGL认为从原点向右的10个单位实际上被认为是距离原点的x个单位数(不同的屏幕分辨率会改变这一点)。这意味着当我的鼠标位于WebGL所考虑的(10,10)上方时,我的鼠标坐标为(100100)

如何将屏幕上的鼠标坐标转换为用于定义点的“WebGL坐标”


这与类似,但我不想使用Fabric.js。

如果事件侦听器位于canvas元素上,那么坐标应该已经位于canvas元素上。这意味着mouse.x=0 mouse.y=0将位于画布的左上角。

如果事件侦听器位于画布元素上,则坐标应该已经位于画布上。意味着鼠标.x=0鼠标.y=0将位于画布的左上角。

要将画布鼠标坐标转换为
-1
+1
范围内的相对坐标,首先需要使用获取画布内的相对像素坐标

然后将其除以画布的实际宽度和高度,使用

使相对坐标在
0
1
的范围内,我们现在可以通过乘以
2
并减去
1
将它们移动到正确的范围内

请注意,在WebGL中,上轴为正
1
,因此需要反转Y坐标

所有这些加在一起:

var ndcX = (mouseEvent.offsetX / canvas.clientWidth) * 2 - 1;
var ndcY = (1 - (mouseEvent.offsetY / canvas.clientHeight)) * 2 - 1;

要将画布鼠标坐标转换为
-1
+1
范围内的相对坐标,首先需要使用获取画布内的相对像素坐标

然后将其除以画布的实际宽度和高度,使用

使相对坐标在
0
1
的范围内,我们现在可以通过乘以
2
并减去
1
将它们移动到正确的范围内

请注意,在WebGL中,上轴为正
1
,因此需要反转Y坐标

所有这些加在一起:

var ndcX = (mouseEvent.offsetX / canvas.clientWidth) * 2 - 1;
var ndcY = (1 - (mouseEvent.offsetY / canvas.clientHeight)) * 2 - 1;

看起来这可能有用。让我再做一点测试,但看起来不错。这不起作用。画布中的10个单位宽是onmousmove事件侦听器报告的20多个单位,即使在画布元素上也是如此。由于mouse.x/y返回的值与event.clientX/y相同,这意味着坐标将相对于视口而不是元素。并非所有浏览器都支持x/y。看起来这可能有用。让我再做一点测试,但看起来不错。这不起作用。画布中的10个单位宽是onmousmove事件侦听器报告的20多个单位,即使在画布元素上也是如此。由于mouse.x/y返回的值与event.clientX/y相同,这意味着坐标将相对于视口而不是元素。并非所有浏览器都支持x/y。Ref:添加了webgl标记Ref。注释默认NDC空间(无任何转换)在屏幕左侧为x=-1,右侧为x=+1;y=-1位于屏幕底部,y=+1位于屏幕顶部。我的问题是如何将视口中的光标坐标转换为NDC空间中的光标坐标。或者使用基本数学:
mx=(mouseEvent.offsetX/canvas.clientWidth)*2-1
与y相同,使用
offsetY
clientHeight
添加了webgl标记参考注释默认NDC空间(无任何转换)在屏幕左侧为x=-1,右侧为x=+1;y=-1位于屏幕底部,y=+1位于屏幕顶部。我的问题是如何将视口中的光标坐标转换为NDC空间中的光标坐标。或者使用基本数学:
mx=(mouseEvent.offsetX/canvas.clientWidth)*2-1
使用
offsetY
clientHeight
与y相同,但在正常情况下,您的解决方案在
ndcY
计算中的输入错误较小。您应该通过
canvas.clientHeight
而不是
canvas.clientWidth
进行分隔。比看起来更难,但在正常情况下,您的解决方案在
ndcY
计算中会出现小错误。您应该通过
canvas.clientHeight
而不是
canvas.clientWidth
进行分隔。