Converting Mouse Event Coordinates to Canvas Coordinate


The coordinate system of a HTML5 canvas object starts with 0,0 in its upper left hand corner. Coordinate system for a mouse event object, on the other hand, is highly ambiguous. QuirksMode has a detail discussion on this topic. If you are developing an interactive drawing application, you will need to convert mouse event coordinates to the coordinate system of a canvas.

Based on the QuirksMode article, I developed these utility methods that can do the conversion. I have only tested this with FF 3.6.8.

/*
 * Get mouse event coordinate converted to canvas coordinate
 * c: The canvas object
 * e: A mouse event
 */
function toCanvasX(c, e) {
  var posx = 0;
  
  if (e.pageX)   {
    posx = e.pageX;
  } else if (e.clientX)   {
    posx = e.clientX + document.body.scrollLeft
      + document.documentElement.scrollLeft;
  }
  posx = posx - c.offsetLeft;
  return posx;
}

function toCanvasY(c, e) {
  var posy = 0;
  
  if (e.pageY)   {
    posy = e.pageY;
  } else if (e.clientY)   {
    posy = e.clientY + document.body.scrollTop
      + document.documentElement.scrollTop;
  }
  posy = posy - c.offsetTop;
  
  return posy;
}

Below is an example application that uses these methods. This is perhaps one of the simplest interactive drawing applications using HTML 5 canvas.

<!DOCTYPE html>
<html>
<head>
<title>Canvas Test</title>

<script type="text/javascript">
// globals
var x = 0;
var y = 0;

function init() {
	var canvas = document.getElementById('canvas');
	canvas.addEventListener("mousedown", drawLine, false);
}

/*
 * Get mouse event coordinate converted to canvas coordinate
 * c: The canvas object
 * e: A mouse event
 */
function toCanvasX(c, e) {
  var posx = 0;
  
  if (e.pageX)   {
    posx = e.pageX;
  } else if (e.clientX)   {
    posx = e.clientX + document.body.scrollLeft
      + document.documentElement.scrollLeft;
  }
  posx = posx - c.offsetLeft;
  return posx;
}

function toCanvasY(c, e) {
  var posy = 0;
  
  if (e.pageY)   {
    posy = e.pageY;
  } else if (e.clientY)   {
    posy = e.clientY + document.body.scrollTop
      + document.documentElement.scrollTop;
  }
  posy = posy - c.offsetTop;
  
  return posy;
}

function drawLine(e) {
  var posx = toCanvasX(this, e);
  var posy = toCanvasY(this, e);
  var ctx= this.getContext('2d');

  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(posx, posy);
  ctx.stroke();
  
  x = posx;
  y = posy;
}
</script>

</head>

<body onload="init();">

<canvas id="canvas" width="500" height="500" style="border: 1px dotted;">
      This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</body>
</html>
  1. #1 by Lon Hosford on October 23, 2011 - 4:44 pm

    I deployed Bibhas’ code in an example where an arrow rotates to point to the mouse position.

    http://www.lonhosford.com/lonblog/2011/10/23/html5-canvas-based-animation-rotate-arrow-to-mouse-position/

(will not be published)

*