Javascript 定位相对于变换平面的鼠标位置
我已经建立了一个JSFIDLE来说明我的情况:Javascript 定位相对于变换平面的鼠标位置,javascript,css,canvas,css-transforms,Javascript,Css,Canvas,Css Transforms,我已经建立了一个JSFIDLE来说明我的情况: 基本上,我有三个嵌套的HTML元素:一个外部的视口div,中间的一个div,里面有一个画布。stage div为应用于画布的三维变换提供透视设置。视口有溢出:隐藏这样我们就看不到视口之外的任何东西。它还附加了一个侦听器,用于侦听mousedown 在我正在构建的实际应用程序中,画布可能会转换为任意3d转换,包括3d空间中的平移和旋转。我希望viewport div拦截单击,并在画布上单击的位置绘制一个点。我用viewport div截取事件,并在C
基本上,我有三个嵌套的HTML元素:一个外部的视口div,中间的一个div,里面有一个画布。stage div为应用于画布的三维变换提供透视设置。视口有
溢出:隐藏代码>这样我们就看不到视口之外的任何东西。它还附加了一个侦听器,用于侦听mousedown
在我正在构建的实际应用程序中,画布可能会转换为任意3d转换,包括3d空间中的平移和旋转。我希望viewport div拦截单击,并在画布上单击的位置绘制一个点。我用viewport div截取事件,并在Chrome中使用offsetX和offsetY。这对Chrome非常有用,但我知道我不能在其他浏览器中依赖offsetX和offsetY,所以我想使用pageX和pageY,通过jQuery进行规范化,但我不确定如何做到这一点
我目前在JSFIDLE中得到的东西在Chrome中非常有用,除非你在视口中而不是画布上单击。当您单击画布时,无论画布的变换如何,它都会在画布上绘制一个点。Chrome做了所有艰苦的工作,给了我想要的offsetX和offsetY。但是,当您在视口中而不是在画布上单击时,我猜它会给出相对于视口(而不是画布)的偏移量x和偏移量值,然后解释该值并在画布上绘制一个点。例如,如果我变换画布,然后单击视口的右上角,则画布的右上角会出现一个点,而不管该角在页面上的实际位置如何
然而,在Firefox中,只要画布上没有应用任何转换,它就可以很好地工作,但一旦画布被转换,正在绘制的点就会突然发生位移,我无法确定如何获取我的pageX和pageY值,并确定我在画布中单击的确切位置
有人有什么绝妙的解决办法吗?我对这个问题的抨击已经太久了。我很确定我需要手动计算一些3d变换矩阵之类的东西,我花了几个小时写了一些方法来返回矩阵的逆矩阵,矩阵乘以向量等等,但这些都没有真正解决我的问题,我也不确定我遗漏了什么
Stackoverflow说JSFIDLE链接需要代码,所以下面是我的所有代码:
HTML:
Javascript:
var counter = 0;
$('#viewport').mousedown(function _drawOnCanvas (e)
{
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var xpos, ypos;
if (typeof e.offsetX=='undefined')
{
xpos = e.pageX - $('#myCanvas').offset().left;
ypos = e.pageY - $('#myCanvas').offset().top;
}
else
{
xpos = e.offsetX;
ypos = e.offsetY;
}
ctx.fillRect(xpos-5, ypos-5, 10, 10);
});
function transformMe()
{
counter++;
var angle = (counter * 30) % 360;
$('#myCanvas').css('transform','perspective(1000px) rotate3d(5,6,7,' + angle + 'deg)');
$('input').val('counter: ' + counter + ', angle: ' + angle);
};
对于Firefox,您可以使用和。可以把它们想象成Firefox版本的offsetX
&offsetY
演示:
JAVASCRIPT:
var counter = 0;
$('#viewport').mousedown(function _drawOnCanvas (e)
{
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var xpos, ypos;
if (typeof e.offsetX=='undefined')
{
xpos = e.originalEvent.layerX;
ypos = e.originalEvent.layerY;
}
else
{
xpos = e.offsetX;
ypos = e.offsetY;
}
ctx.fillRect(xpos-5, ypos-5, 10, 10);
});
function transformMe()
{
counter++;
var angle = (counter * 30) % 360;
$('#myCanvas').css('transform','perspective(1000px) rotate3d(5,6,7,' + angle + 'deg)');
$('input').val('counter: ' + counter + ', angle: ' + angle);
};
若在Kyle或Dom的jsfiddles的第3行中将视口更改为myCanvas,则:
$('#myCanvas').mousedown(function _drawOnCanvas (e)
当您“在视口中而不是在画布上单击”时,它不再放置点
Firefox似乎有一个新的问题——如果有一个转换,它只允许你在一半(对角线的左下角)上绘画,但取决于转换。谢谢;这可能对我有用。这只是我试图解决的问题中的一个步骤,即当我的#myCanvas
已转换,但自转换后鼠标未移动时,获取更新的鼠标位置。我相信如果我取前一个鼠标位置,将向量乘以前一个变换矩阵的倒数,然后将得到的向量乘以当前变换矩阵,就可以了。对吗?最新的Firefox支持offsetX和offsetY。然而,他们不尊重3D转换元素,就像在Chrome中一样。仍在努力找到解决办法。layerX在FireFox中仍然尊重它,但现在更难决定何时使用layerX,因为我无法再检查offsetX是否未定义。现在可能需要为Firefox添加特殊检查。这里似乎应该有一个使用实际矩阵的解决方案,但我还没有弄清楚
var counter = 0;
$('#viewport').mousedown(function _drawOnCanvas (e)
{
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var xpos, ypos;
if (typeof e.offsetX=='undefined')
{
xpos = e.originalEvent.layerX;
ypos = e.originalEvent.layerY;
}
else
{
xpos = e.offsetX;
ypos = e.offsetY;
}
ctx.fillRect(xpos-5, ypos-5, 10, 10);
});
function transformMe()
{
counter++;
var angle = (counter * 30) % 360;
$('#myCanvas').css('transform','perspective(1000px) rotate3d(5,6,7,' + angle + 'deg)');
$('input').val('counter: ' + counter + ', angle: ' + angle);
};
$('#myCanvas').mousedown(function _drawOnCanvas (e)