Unfortunately offsetX and layerX are not exactly the same as offsetX is the offset within the current element but layerX is the offset from the page. Below is a fix I am currently using for this:
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;
}
I found that all answers posted here except the last two answers by EnotionZ and laz brannigan (previously with zero votes each) where wrong in cases where several elements were contained within a div. In my case I have several canvas elements inside of a single div and I am listening to each canvas separately.
After considerable trial and error the final correct answer I came to, which works perfectly and identically for me in FireFox and Chrome is as follows:
//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);
Presumably this will also work for margins and such as EnotionZ indicated in his post, but I have not tried that.
There's a bug in Musa's solution: think what happens if e.offsetX === 0
and e.layerX === undefined
...
var x = e.offsetX || e.layerX; // x is now undefined!
A more robust version is as follows:
var x = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX;
var y = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY;
Or, because we can assume that if offsetX
is defined, offsetY
will be too:
var hasOffset = e.hasOwnProperty('offsetX'),
x = hasOffset ? e.offsetX : e.layerX,
y = hasOffset ? e.offsetY : e.layerY;
offset
actually doesn't translate directly into layer
; the offset
property doesn't account for the element's margin. The code below should account for this.
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;
}
}
None of the non-jquery versions work completely for various reasons. With your help however i got this to work:
if(!event.hasOwnProperty('offsetX')) {
event.offsetX = event.layerX - event.currentTarget.offsetLeft;
event.offsetY = event.layerY - event.currentTarget.offsetTop;
}