Is there a way to get the location mouse inside a <canvas>
tag? I want the location relative to to the upper right corner of the <canvas>
, not the entire page.

- 75,346
- 19
- 113
- 141

- 7,049
- 10
- 42
- 47
9 Answers
The accepted answer will not work every time. If you don't use relative position the attributes offsetX and offsetY can be misleading.
You should use the function: canvas.getBoundingClientRect()
from the canvas API.
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
}, false);

- 1,157
- 8
- 11
-
1this should be the accepted answer – Antonin Cezard Sep 16 '16 at 06:37
Easiest way is probably to add a onmousemove event listener to the canvas element, and then you can get the coordinates relative to the canvas from the event itself.
This is trivial to accomplish if you only need to support specific browsers, but there are differences between f.ex. Opera and Firefox.
Something like this should work for those two:
function mouseMove(e)
{
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
/* do something with mouseX/mouseY */
}

- 42,745
- 10
- 68
- 86
-
5I'd highly recommend using JQuery or some other javascript framework that standardizes offsets. – Soviut Jul 14 '09 at 05:22
-
4This only worked for me if I set the canvas position to be relative as suggested By Nat. – Richard Garside Aug 09 '10 at 10:28
-
4@Richard - That's because `layerX` and `layerY` are relative to the *entire document* for non-positioned elements. See my answer here for more info: http://stackoverflow.com/questions/5085689/tracking-mouse-position-in-canvas – Wayne Dec 26 '11 at 22:37
-
6If the e.offsetX is defined, but equal to 0, then this code does the wrong thing. – prideout Feb 09 '13 at 19:21
Also note that you'll need CSS:
position: relative;
set to your canvas tag, in order to get the relative mouse position inside the canvas.
And the offset changes if there's a border

- 18,111
- 2
- 28
- 31

- 231
- 2
- 2
-
1been scouring the internet to find out why Firefox (7) was reporting a strange value for the layerY - this fixed it, many thanks! – Mikey Nov 06 '11 at 01:46
-
-
-
+1 This fixed the 5-10 pixel offset issue I was having in FF 11. Thanks! – Mike Moore Apr 25 '12 at 04:38
-
This isn't the *only* or *necessary* way to do it. What this answer *should* have explained is that `e.layerX` and `e.layerY` are relative to the canvas when it is a positioned element, but relative to the entire document when it is not. Note that these properties are not part of any standard. There are better ways to do this. – Wayne Jan 05 '14 at 19:40
I'll share the most bulletproof mouse code that I have created thus far. It works on all browsers will all manner of padding, margin, border, and add-ons (like the stumbleupon top bar)
// Creates an object with x and y defined,
// set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky,
// we have to worry about padding and borders
// takes an event and a reference to the canvas
function getMouse = function(e, canvas) {
var element = canvas, offsetX = 0, offsetY = 0, mx, my;
// Compute the total offset. It's possible to cache this if you want
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
// Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
// This part is not strictly necessary, it depends on your styling
offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
offsetY += stylePaddingTop + styleBorderTop + htmlTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
// We return a simple javascript object with x and y defined
return {x: mx, y: my};
}
You'll notice that I use some (optional) variables that are undefined in the function. They are:
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
var html = document.body.parentNode;
htmlTop = html.offsetTop;
htmlLeft = html.offsetLeft;
I'd recommend only computing those once, which is why they are not in the getMouse
function.

- 62,212
- 13
- 141
- 171
-
1awesome little utility method. I think in most cases you won't need to compute the canvas offsets every time too. – uchamp Feb 19 '15 at 07:40
For mouse position, I usually use jQuery since it normalizes some of the event attributes.
function getPosition(e) {
//this section is from http://www.quirksmode.org/js/events_properties.html
var targ;
if (!e)
e = window.event;
if (e.target)
targ = e.target;
else if (e.srcElement)
targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
// jQuery normalizes the pageX and pageY
// pageX,Y are the mouse positions relative to the document
// offset() returns the position of the element relative to the document
var x = e.pageX - $(targ).offset().left;
var y = e.pageY - $(targ).offset().top;
return {"x": x, "y": y};
};
// now just make sure you use this with jQuery
// obviously you can use other events other than click
$(elm).click(function(event) {
// jQuery would normalize the event
position = getPosition(event);
//now you can use the x and y positions
alert("X: " + position.x + " Y: " + position.y);
});
This works for me in all the browsers.
EDIT:
I copied the code from one of my classes I was using, so the jQuery call to this.canvas
was wrong. The updated function figures out which DOM element (targ
) caused the event and then uses that element's offset to figure out the correct position.

- 27,207
- 17
- 105
- 121
GEE is an endlessly helpful library for smoothing out troubles with canvas, including mouse location.

- 78,257
- 17
- 139
- 164

- 208
- 4
- 8
-
-
3GEE is no longer maintained and dubbed by the developer(s) as "Totally deprecated." – arkon Oct 09 '12 at 09:08
Simple approach using mouse event and canvas properties:
JSFiddle demo of functionality http://jsfiddle.net/Dwqy7/5/
(Note: borders are not accounted for, resulting in off-by-one):
Add a mouse event to your canvas
canvas.addEventListener("mousemove", mouseMoved);
Adjust
event.clientX
andevent.clientY
based on:
canvas.offsetLeft
window.pageXOffset
window.pageYOffset
canvas.offsetTop
Thus:canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset); canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
The original question asked for coordinates from the upper right (second function). These functions will need to be within a scope where they can access the canvas element.
0,0 at upper left:
function mouseMoved(event){
var canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
0,0 at upper right:
function mouseMoved(event){
var canvasMouseX = canvas.width - (event.clientX - canvas.offsetLeft)- window.pageXOffset;
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}

- 21
- 3
-
The off-by-1-pixel is your 1px border (borders and padding do count). You also should account for scrolling...Cheers! :-) – markE May 31 '14 at 20:19
-
@markE Thanks for the heads up; I've adjusted the code above and in the JSFiddle to account for scrolling. I couldn't find a way to adjust for the canvas border. – Keving May 31 '14 at 23:12
I'd use jQuery.
$(document).ready(function() {
$("#canvas_id").bind( "mousedown", function(e){ canvasClick(e); } );
}
function canvasClick( e ){
var x = e.offsetX;
var y = e.offsetY;
}
This way your canvas can be anywhere on your page, relative or absolute.

- 2,214
- 24
- 24
Subtract the X and Y offsets of the canvas DOM element from the mouse position to get the local position inside the canvas.

- 88,194
- 49
- 192
- 260
-
3How do you get the X and Y of the canvas dom element in a way that works accross all browsers? – Richard Garside Aug 09 '10 at 10:31
-
1
-
1Mind telling me why my advice is "bunk"? Do you think it's incorrect, not detailed enough, etc? That would have been a lot more helpful. Besides, my rep doesn't necessarily mean my answers are going to be perfect, that's why there's a voting system. Don't agree? Then vote it down. – Soviut Oct 09 '12 at 20:16
-
i did vote down. this is only looking like an answer. It is not. – GameAlchemist Nov 08 '12 at 19:35
-
1Can you please explain what I should add to the answer to make it better. I agree it's fairly general and maybe needs a code example, etc. But so far people have just said "not good answer". – Soviut Nov 08 '12 at 23:55
-
1You could add how to get the (x,y) position from the DOM element. – Ramy Al Zuhouri Oct 10 '13 at 11:19