What\'s the simplest way to add a click event handler to a canvas element that will return the x and y coordinates of the click (relative to the canvas element)?
No
I made a full demostration that works in every browser with the full source code of the solution of this problem: Coordinates of a mouse click on Canvas in Javascript. To try the demo, copy the code and paste it into a text editor. Then save it as example.html and, finally, open the file with a browser.
According to fresh Quirksmode the clientX
and clientY
methods are supported in all major browsers.
So, here it goes - the good, working code that works in a scrolling div on a page with scrollbars:
function getCursorPosition(canvas, event) {
var x, y;
canoffset = $(canvas).offset();
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor(canoffset.left);
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor(canoffset.top) + 1;
return [x,y];
}
This also requires jQuery for $(canvas).offset()
.
See demo at 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 };
}
Modern browser's now handle this for you. Chrome, IE9, and Firefox support the offsetX/Y like this, passing in the event from the click handler.
function getRelativeCoords(event) {
return { x: event.offsetX, y: event.offsetY };
}
Most modern browsers also support layerX/Y, however Chrome and IE use layerX/Y for the absolute offset of the click on the page including margin, padding, etc. In Firefox, layerX/Y and offsetX/Y are equivalent, but offset didn't previously exist. So, for compatibility with slightly older browsers, you can use:
function getRelativeCoords(event) {
return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}