Javascript 定位相对于变换平面的鼠标位置

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

我已经建立了一个JSFIDLE来说明我的情况:

基本上,我有三个嵌套的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)