Firefox中的event.offsetX

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script language="javascript"> function main(){ var canvas = document.getElementById("canvas"); canvas.addEventListener("mousemove", function(e){ if (!e) e = window.event; var ctx = canvas.getContext("2d"); var x = e.offsetX; var y = e.offsetY; ctx.fillRect(x, y, 1, 1); }); } </script> </head> <body onload="main();"> <div style="width: 800px; height: 600px; -webkit-transform: scale(0.75,0.75); -moz-transform: scale(0.75,0.75)"> <canvas id="canvas" width="400px" height="400px" style="background-color: #cccccc;"></canvas> </div> </body> </html> 

请考虑上面的快速和肮脏的例子。 请注意,我的canvas包含在一个具有比例变换的div中。 上面的代码完全适用于任何基于webkit的浏览器。 在移动鼠标的同时在canvas上绘制点。 不幸的是,它不在Firefox中,因为它的事件模型不支持offsetX / Y属性。 我怎么能(也许)event.clientX(也支持在Firefox中)的鼠标坐标转换成相对的坐标考虑到canvas的位置,变换等? 谢谢,卢卡。

尝试layerX,layerY

 var x = e.offsetX==undefined?e.layerX:e.offsetX; var y = e.offsetY==undefined?e.layerY:e.offsetY; 

小提琴

从一个JQuery错误跟踪器页面 – 一个不错的polyfill是这样的:

 var offX = (e.offsetX || e.pageX - $(e.target).offset().left); 

其中e是从jquery事件返回的事件。 显然,只有当你的项目中已经有Jquery时,否则将不得不手动执行offset()

不幸的是没有解决scheme为我工作

我在这里find了很好的实现:

 var target = e.target || e.srcElement, rect = target.getBoundingClientRect(), offsetX = e.clientX - rect.left, offsetY = e.clientY - rect.top; e.offsetX = offsetX; e.offsetY = offsetY; 

不幸的是,offsetX和layerX并不完全相同,offsetX是当前元素内的偏移量,但是layerX是偏离页面的偏移量。 下面是我目前使用的一个修复:

 function fixEvent(e) { if (! e.hasOwnProperty('offsetX')) { var curleft = curtop = 0; if (e.offsetParent) { var obj=e; do { curleft += obj.offsetLeft; curtop += obj.offsetTop; } while (obj = obj.offsetParent); } e.offsetX=e.layerX-curleft; e.offsetY=e.layerY-curtop; } return e; } 

在Musa的解决scheme中有一个错误:想想如果e.offsetX === 0e.layerX === undefined会发生什么

 var x = e.offsetX || e.layerX; // x is now undefined! 

更健壮的版本如下:

 var x = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX; var y = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY; 

或者,因为我们可以假设如果定义了offsetXoffsetY也将是:

 var hasOffset = e.hasOwnProperty('offsetX'), x = hasOffset ? e.offsetX : e.layerX, y = hasOffset ? e.offsetY : e.layerY; 

offset实际上并不直接翻译成layer ; offset属性不考虑元素的边距。 下面的代码应该解释这一点。

 function(e) { var x = e.offsetX, y = e.offsetY; if(e.hasOwnProperty('layerX')) { x = e.layerX - e.currentTarget.offsetLeft; y = e.layerY - e.currentTarget.offsetTop; } } 

由于各种原因,没有任何非jQuery版本完全工作。 随着你的帮助,但我得到了这个工作:

 if(!event.hasOwnProperty('offsetX')) { event.offsetX = event.layerX - event.currentTarget.offsetLeft; event.offsetY = event.layerY - event.currentTarget.offsetTop; } 

但是,如果没有layerXlayerY字段,你会怎么做?

  var xe=e.offsetX,ye=e.offsetY; if(!xe){ xe=e.clientX - $(e.target).offset().left; } if(!ye){ ye= e.clientY - $(e.target).offset().top; } 

我发现除了 EnotionZ和laz brannigan的最后两个答案之外(以前每个都是零票),在这里发布的所有答案在多个元素被包含在div内的情况下是错误的。 在我的情况下,我有一个单独的div内的几个canvas元素,我正在分别听每个canvas。

经过相当多的反复试验,我得出了最后的正确答案,这对FireFox和Chrome来说是完美无缺的,同样如此:

 //inside my mouse events handler: var anOffsetX = (inEvent.offsetX !== undefined) ? inEvent.offsetX : (inEvent.layerX - inEvent.target.offsetLeft); var anOffsetY = (inEvent.offsetY !== undefined) ? inEvent.offsetY : (inEvent.layerY - inEvent.target.offsetTop); 

据推测,这也将有利于利润和例如他的post中指出的EnotionZ,但我没有尝试过。

如果有人仍然需要一个解决scheme,这个在Firefox中完美的工作:

 var x = e.offsetX || e.originalEvent.layerX; var y = e.offsetY || e.originalEvent.layerY;