我已经设置了一个说明我情况的小说:http://jsfiddle.net/j5o0w5qc/1/
基本上,我有三个嵌套的HTML元素:外部的视口div,中间的舞台div和内部的画布。 stage div为应用于画布的3d变换提供透视设置。视口有overflow: hidden;
,因此我们无法在视口外看到任何内容。它还附加了一个监听器,监听mousedown
。
在我构建的实际应用中,画布可能会转换为任意三维变换,涉及3d空间中的平移和旋转。我想要发生的是视口div拦截一次点击,并在你点击的地方的画布上画一个点。我使用视口div拦截事件,并且我在Chrome中使用了offsetX和offsetY。这适用于Chrome,但我知道我不能在其他浏览器中依赖offsetX和offsetY,所以我想使用pageX和pageY,通过jQuery进行规范化,但我不确定怎么做。
我目前在jsfiddle中获得的功能在Chrome中效果很好,除非您在视口中单击不在画布上。当您单击画布时,无论画布的转换如何,它都会在那里绘制一个点。 Chrome正在做所有艰苦的工作,并通过offsetX和offsetY向我提供我想要的内容。但是,当您在视口中单击不在画布上时,我猜它会相对于视口而不是画布给出offsetX和offsetY值,然后解释它并在画布上绘制一个点。例如,如果我变换画布然后单击视口的右上角,则无论角落实际出现在页面的哪个角落,都会在画布的右上角出现一个点。
然而,在Firefox中,只要没有应用于画布的转换,它就能很好地工作,但是一旦画布被转换,突然之间,被绘制的点就会被移位,我可以'弄清楚如何获取我的pageX和pageY值,并确定我点击的画布中的确切位置。
有没有人有任何出色的解决方案?我长期以来一直在反对这个问题。我非常确定我需要手动计算一些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);
};
答案 0 :(得分:2)
对于Firefox,您可以使用event.layerX和event.layerY。将它们视为Firefox的offsetX
和&amp; offsetY
。
DEMO: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);
};
答案 1 :(得分:0)
如果您将 Kyle S 或 Dom&#39>的第3行中的视口更改为 myCanvas > jsfiddles:
$('#myCanvas').mousedown(function _drawOnCanvas (e)
当你在视口中点击不在画布上时,它不再放置一个点。&#34;
这似乎是Firefox的一个新问题 - 如果有转换它只能让你画上一半(对角线的左下角 - 但取决于转换)。