views:

6493

answers:

3

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 legacy browser compatibility required, Safari, Opera and Firefox will do.

Update: Thanks @Brian, the following is working (in Opera and FF3 at least):

canvas.addEventListener("click", 
                        function(e) { 
                           alert("x:"+(e.clientX-canvas.offsetLeft)
                                 +" y:"+(e.clientY-canvas.offsetTop)); 
                        }, false);

Update: Note, don't forget to call removeEventListener() if the above code is called more than once or the click handler will be called multiple times...

+3  A: 

Hey, this is in dojo, just cause it's what I had the code in already for a project.

It should be fairly Obvious how to convert it back to non dojo vanilla JavaScript.

  function onMouseClick(e) {
      var x = e.clientX;
      var y = e.clientY;
  }
  var canvas = dojo.byId(canvasId);
  dojo.connect(canvas,"click",onMouseClick);

Hope that helps.

Brian Gianforcaro
+7  A: 

This should not be any different from getting mouse events from normal dom elements. quirksmode has a good reference on that.

toby
+3  A: 

Be wary while doing the coordinate conversion; there are multiple non-cross-browser values returned in a click event. Using clientX and clientY alone are not sufficient if the browser window is scrolled (verified in Firefox 3.5 and Chrome 3.0).

This quirks mode article provides a more correct function that can use either pageX or pageY or a combination of clientX with document.body.scrollLeft and clientY with document.body.scrollTop to calculate the click coordinate relative to the document origin.

UPDATE: Additionally, offsetLeft and offsetTop are relative to the padded size of the element, not the interior size. A canvas with the padding: style applied will not report the top-left of its content region as offsetLeft. There are various solutions to this problem; the simplest one may be to clear all border, padding, etc. styles on the canvas itself and instead apply them to a box containing the canvas.

fixermark