向canvas元素添加一个单击事件处理程序,返回单击的x和y坐标(相对于canvas元素),最简单的方法是什么?
不需要传统浏览器兼容性,Safari、Opera和Firefox就可以了。
向canvas元素添加一个单击事件处理程序,返回单击的x和y坐标(相对于canvas元素),最简单的方法是什么?
不需要传统浏览器兼容性,Safari、Opera和Firefox就可以了。
当前回答
参见http://jsbin.com/ApuJOSA/1/edit?html,output上的演示。
function mousePositionOnCanvas(e) {
var el=e.target, c=el;
var scaleX = c.width/c.offsetWidth || 1;
var scaleY = c.height/c.offsetHeight || 1;
if (!isNaN(e.offsetX))
return { x:e.offsetX*scaleX, y:e.offsetY*scaleY };
var x=e.pageX, y=e.pageY;
do {
x -= el.offsetLeft;
y -= el.offsetTop;
el = el.offsetParent;
} while (el);
return { x: x*scaleX, y: y*scaleY };
}
其他回答
以下是上述Ryan Artecona解决方案的一些修改。
function myGetPxStyle(e,p)
{
var r=window.getComputedStyle?window.getComputedStyle(e,null)[p]:"";
return parseFloat(r);
}
function myGetClick=function(ev)
{
// {x:ev.layerX,y:ev.layerY} doesn't work when zooming with mac chrome 27
// {x:ev.clientX,y:ev.clientY} not supported by mac firefox 21
// document.body.scrollLeft and document.body.scrollTop seem required when scrolling on iPad
// html is not an offsetParent of body but can have non null offsetX or offsetY (case of wordpress 3.5.1 admin pages for instance)
// html.offsetX and html.offsetY don't work with mac firefox 21
var offsetX=0,offsetY=0,e=this,x,y;
var htmls=document.getElementsByTagName("html"),html=(htmls?htmls[0]:0);
do
{
offsetX+=e.offsetLeft-e.scrollLeft;
offsetY+=e.offsetTop-e.scrollTop;
} while (e=e.offsetParent);
if (html)
{
offsetX+=myGetPxStyle(html,"marginLeft");
offsetY+=myGetPxStyle(html,"marginTop");
}
x=ev.pageX-offsetX-document.body.scrollLeft;
y=ev.pageY-offsetY-document.body.scrollTop;
return {x:x,y:y};
}
嘿,这是在dojo,只是因为它是我已经在一个项目的代码。
如何将其转换回非dojo的普通JavaScript应该是相当明显的。
function onMouseClick(e) {
var x = e.clientX;
var y = e.clientY;
}
var canvas = dojo.byId(canvasId);
dojo.connect(canvas,"click",onMouseClick);
希望这能有所帮助。
现代浏览器现在可以帮你处理这个。Chrome, IE9和Firefox支持这样的offsetX/Y,从点击处理程序传入事件。
function getRelativeCoords(event) {
return { x: event.offsetX, y: event.offsetY };
}
大多数现代浏览器也支持layerX/Y,但是Chrome和IE使用layerX/Y作为页面点击的绝对偏移量,包括边距、填充等。在Firefox中,layerX/Y和offsetX/Y是等价的,但是offset之前并不存在。所以,为了兼容稍微老一点的浏览器,你可以使用:
function getRelativeCoords(event) {
return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}
如果你喜欢简单,但仍然需要跨浏览器功能,我发现这个解决方案最适合我。这是一个简化的@Aldekein的解决方案,但没有jQuery。
function getCursorPosition(canvas, event) {
const rect = canvas.getBoundingClientRect()
const x = event.clientX - rect.left
const y = event.clientY - rect.top
console.log("x: " + x + " y: " + y)
}
const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
getCursorPosition(canvas, e)
})
在进行坐标转换时要小心;在单击事件中返回多个非跨浏览器的值。如果浏览器窗口是滚动的(在Firefox 3.5和Chrome 3.0中验证),仅使用clientX和clienti是不够的。
这篇怪异模式文章提供了一个更正确的函数,可以使用pageX或pageY,或者使用clientX与document.body. scrollleft和clienti与document.body. scrolltop的组合来计算相对于文档原点的单击坐标。
更新:另外,offsetLeft和offsetTop是相对于元素的填充大小,而不是内部大小。应用了padding: style的画布不会将其内容区域的左上角报告为offsetLeft。这个问题有多种解决方案;最简单的方法可能是清除画布本身的所有边框、填充等样式,而是将它们应用到包含画布的框中。