我已经设置了一个 jsfiddle 来说明我的情况:http://jsfiddle.net/j5o0w5qc/1/
基本上,我有三个嵌套的 HTML 元素:外部的视口(viewport) div、中间的舞台 div 和内部的 Canvas 。舞台 div 为应用于 Canvas 的 3d 变换提供透视设置。视口(viewport)有 overflow: hidden;
所以我们看不到视口(viewport)之外的任何东西。它还附加了一个监听器,用于监听 mousedown
。
在我正在构建的实际应用程序中, Canvas 可能会转换为任意 3d 转换,涉及 3d 空间中的平移和旋转。我想要发生的是让视口(viewport) div 拦截点击,并在 Canvas 上点击的地方画一个点。我正在使用视口(viewport) div 拦截事件,并且在 Chrome 中使用 offsetX 和 offsetY。这对 Chrome 非常有用,但我知道我不能依赖其他浏览器中的 offsetX 和 offsetY,所以我想使用 pageX 和 pageY,通过 jQuery 规范化,但我不太确定该怎么做。
我目前在 jsfiddle 中获得的内容在 Chrome 中运行良好,除非您在视口(viewport)中单击而不是在 Canvas 上。当您单击 Canvas 时,它会在那里绘制一个点,而不管 Canvas 的变换如何。 Chrome 正在做所有艰苦的工作,并通过 offsetX 和 offsetY 为我提供我想要的东西。但是,当您在不在 Canvas 上的视口(viewport)中单击时,我想它会给我相对于视口(viewport)而不是 Canvas 的 offsetX 和 offsetY 值,然后解释它并在 Canvas 上绘制一个点。例如,如果我变换 Canvas 然后单击视口(viewport)的右上角,则 Canvas 的右上角会出现一个点,而不管该 Angular 实际出现在页面上的什么位置。
然而,在 Firefox 中,只要没有对 Canvas 应用任何变换,它就可以很好地工作,但是一旦 Canvas 被变换,突然之间,绘制的点就会移位,我想不通弄清楚如何获取我的 pageX 和 pageY 值并找出我在 Canvas 中单击的确切位置。
有没有人有什么绝妙的解决方案?我一直在为这个问题苦苦思索太久了。我很确定我需要手动计算一些 3d 变换矩阵或其他东西,我花了几个小时编写方法来返回矩阵的逆矩阵,将矩阵乘以向量,以及各种各样的东西,但没有它实际上已经为我解决了问题,我不确定我错过了什么。
Stackoverflow 说 jsfiddle 链接需要代码,所以这是我的所有代码:
HTML:
<div id="viewport">
<div id="stage">
<canvas id="myCanvas" width="300" height="300"></canvas>
</div>
</div>
<div id="stuff">
<button onclick="transformMe()">Transform</button>
<input id="blah" type="text" size="45"></input>
</div>
CSS:
#viewport, #stage, #myCanvas {
width: 300px;
height: 300px;
position: absolute;
top: 0;
left: 0;
}
#viewport {
border: 1px solid #000;
overflow: hidden;
}
#stage {
perspective: 1000px;
transform-style: preserve-3d;
}
#myCanvas {
background-color: green;
transform-style: preserve-3d;
}
#stuff {
position: absolute;
top: 350px;
}
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,您可以使用 event.layerX和 event.layerY .将它们视为 Firefox 的 offsetX
和 offsetY
版本。
演示:http://jsfiddle.net/dirtyd77/j5o0w5qc/3/
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);
};
关于javascript - 定位鼠标相对于变换平面的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26070194/