DEV Community

David Miller
David Miller

Posted on

Map pointer coordinates into the canvas drawing buffer

Convert the pointer position into drawing-buffer coordinates before drawing a marker on a resized canvas. The event reports viewport coordinates, while the drawing buffer has its own width and height.

For a canvas displayed at half its buffer width, one CSS pixel covers two buffer pixels. Subtracting the canvas position gives a local CSS coordinate. Multiply that value by the buffer-to-display ratio before drawing a marker or choosing a crop boundary.

function canvasPoint(canvas, event) {
  const rect = canvas.getBoundingClientRect();
  if (rect.width === 0 || rect.height === 0) return null;
  return {
    x: (event.clientX - rect.left) * canvas.width / rect.width,
    y: (event.clientY - rect.top) * canvas.height / rect.height
  };
}
Enter fullscreen mode Exit fullscreen mode

This example assumes an axis-aligned canvas with no CSS border or padding and no rotation or skew. Put a decorative border on a wrapper. The bounding rectangle includes border and padding, so those would need separate handling if placed on the canvas itself.

The returned coordinates describe the canvas buffer. If the drawing context has a transform, or if the photo is letterboxed inside that buffer, mapping into the photo requires another step. Reject clicks outside the displayed photo before calculating a crop.

Check the mapping near both corners after resizing the page. If a marker follows the pointer near the upper-left corner but drifts near the lower-right, check the scale conversion. Read the current rectangle for the interaction; a rectangle saved before a layout change can be stale.

Reference: MDN

Top comments (0)