Explain Codes LogoExplain Codes Logo

Zoom Canvas to Mouse Cursor

javascript
canvas-api
zoom-animation
mouse-events
Nikita BarsukovbyNikita Barsukov·Jan 3, 2025
TLDR

To zoom into a canvas at the mouse position, we need to scale and re-center the canvas context. Here's how:

  1. Translate the context position to the mouse point.
  2. Scale the context by your zoom factor.
  3. Translate back by adjusting for the new zoom level.

Below is the essential part of this process in JavaScript:

function zoomAtCursor(canvas, ctx, zoomFactor, cursorX, cursorY) { // Get the bounding rectangle of the canvas var rect = canvas.getBoundingClientRect(); // Compute the offset for the zoom center var offsetX = (cursorX - rect.left) * (1 - zoomFactor); var offsetY = (cursorY - rect.top) * (1 - zoomFactor); // Our magic! A waltz of translate, scale, translate. ctx.translate(offsetX, offsetY); ctx.scale(zoomFactor, zoomFactor); ctx.translate(-offsetX, -offsetY); // Now with our context transformed, we're ready to draw! }

Call zoomAtCursor providing your zoom factor and cursor coordinates, effectively achieving a zoom effect centered at the mouse position.

Key Pivotal Aspects

Handling Mouse Events & Touch Gestures

A refined zoom feature caters for different interactions:

  • Click for zoom in.
  • Shift-click for zoom out.
  • Mouse drag for panning.
  • Pinch gestures for zooming on touch devices.

Matrix Operations and Performance

Scaling and translating are matrix operations. To ensure performance, use ctx.setTransform instead of stacked transformations. After scaling is done, reset transformations using ctx.setTransform(1, 0, 0, 1, 0, 0).

Clear the Canvas

Before redrawing, clear the canvas to prevent previous drawings from getting in the way of the new ones:

ctx.clearRect(0, 0, canvas.width, canvas.height); //It's... Poof, gone!

Utilizing Libraries & External Functions

Libraries like Loupe, CanvasZoom, or Scroller can help to ease the task. These libraries also ensure tasks like complex matrix inversions are handled efficiently and without redundant code.

Zoom Animation

Using requestAnimationFrame can ease the transition which provides smooth zoom animations, especially important when developing for lower-performing devices:

function animateZoom(canvas, ctx, targetZoom, cursorX, cursorY, steps) { var currentStep = 0; (function step() { if (currentStep++ < steps) { var zoomFactor = 1 + (targetZoom - 1) * currentStep / steps; zoomAtCursor(canvas, ctx, zoomFactor, cursorX, cursorY); requestAnimationFrame(step); // Call me maybe? } })(); }

The Magic of Visualisation

Imagine you are an astronaut, exploring the cosmos and suddenly, you find a new planet. With your high-tech telescope, you are adjusting the focus on the planet. You can adjust the view perfectly until the planet is in the center.

Before Zoom: [👨‍🚀🔭🌌🪐] (You spotted a new planet) After Zoom: [👨‍🚀🔭🪐🌌] (The new planet is now in center view)

The zoom on canvas is similar to adjusting the telescope. The mouse cursor acts as the lens adjustment.

Initial View: [🖼️🐁🌌🌠] (Cursor hovers over the star) Zoomed In: [🌌🌠🐁🌌] (The star remains under the cursor while zoomed)

This allows the point of interest beneath the mouse point to keep focused when zooming.

Paving the Path with References

  1. Canvas API - Web APIs | MDN — MDN's comprehensive guide to the HTML Canvas API.
  2. Real mouse position in canvas - Stack Overflow — Here's a Stack Overflow thread that digs into getting the accurate cursor position over a canvas.
  3. Coding Dude: Web Development, JS, HTML, CSS, SEO — Dive into matrix math for affine transformations, applicable for our zooming techniques.
  4. GitHub - anvaka/panzoom: Universal pan and zoom library (DOM, SVG, Custom) - A universal pan and zoom library on GitHub for canvas and other web elements.
  5. CodePen Example - and finally, CodePen's demo on zooming to the mouse cursor in a canvas.