18

I'm having trouble in getting the mouse position w.r.t canvas.

There are two cases:

1) If there is no div element surrounding the canvas div then I was able to get the mouse position.

2) When the canvas is wrapped in a div then offsetLeft and offsetTop do not work as expected

What accounts for this difference?

Wayne
  • 59,728
  • 15
  • 131
  • 126
dragonfly
  • 3,203
  • 7
  • 30
  • 52
  • Duplicate of [Mouse position within HTML 5 Canvas](http://stackoverflow.com/questions/4915326/mouse-position-within-html-5-canvas) (and [Getting Mouse Location in Canvas](http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas) and [Getting Mouse Position with JavaScript within Canvas](http://stackoverflow.com/questions/4848310/getting-mouse-position-with-javascript-within-canvas)). – Phrogz Feb 23 '11 at 02:25
  • @Phrogz is right that this has been asked many times before. I didn't point this out, because each of the referenced posts has flawed accepted answers. The first one misses the point, the second one is just wrong, and the third one unnecessarily extends the DOM and reinvents the wheel. Since they have accepted answers, I'm not sure how to best get the correct solution in front of eyeballs. This is a problem. – Wayne Feb 23 '11 at 04:54
  • >>unnecessarily extends the DOM and reinvents the wheel.<< You mean my prepareCanvas()?? I thought this way, it will work even in IE. Correct me if I'm wrong. – dragonfly Feb 23 '11 at 06:23
  • 1
    @Priya - I was referring to the `Element.prototype.leftTopScreen` solution in the third link given by @Phrogz, which does exactly what my `findPos` does below, but does so by modifying the `Element` prototype. This is generally a bad idea. See this link: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – Wayne Feb 23 '11 at 15:39
  • @Priya - see my answer below. Your only problem is that you were calculating the offset relative to the parent `div`, when you wanted to calculate the offset relative to the `canvas`. The solution I provided should work for you. – Wayne Feb 23 '11 at 15:41
  • possible duplicate of [How do I get the coordinates of a mouse click on a canvas element?](http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element) – user Oct 01 '12 at 15:05

1 Answers1

29

You need a function to get the position of the canvas element:

function findPos(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

And calculate the current position of the cursor relative to that:

$('#canvas').mousemove(function(e) {
    var pos = findPos(this);
    var x = e.pageX - pos.x;
    var y = e.pageY - pos.y;
    var coordinateDisplay = "x=" + x + ", y=" + y;
    writeCoordinateDisplay(coordinateDisplay);
});

The values of offsetLeft and offsetTop are relative to offsetParent, which is your div node. When you remove the div they're relative to the body, so there is no offset to subtract.

Similary, e.pageX and e.pageY give the position of the cursor relative to the document. That's why we subtract the canvas's offset from those values to arrive at the true position.

An alternative for positioned elements is to directly use the values of e.layerX and e.layerY. This is less reliable than the method above for two reasons:

  1. These values are also relative to the entire document when the event does not take place inside a positioned element
  2. They are not part of any standard
Wayne
  • 59,728
  • 15
  • 131
  • 126
  • Could these coordinates be stored clientside in a file that is not cleared after each session? – HCAI May 04 '12 at 16:56
  • Sure. Put them in a cookie or local storage. – Wayne Jul 06 '12 at 19:10
  • I like how this answer to something that's "not a real question" got another upvote on the second anniversary of its closing. – Wayne Oct 01 '14 at 21:33