SVG — Interactive Pan & Zoom Map

Drag to pan, scroll to zoom toward the cursor. There is no transform on the shapes — we just move the viewBox window from Part 1. Click a region to highlight it.

drag · scroll-zoom · click

zoom toward the cursor
function zoomAt(factor, mouseUserX, mouseUserY) {
  vb.w *= factor; vb.h *= factor;          // scale the window
  // keep the point under the cursor fixed:
  vb.x = mouseUserX - (mouseUserX - vb.x) * factor;
  vb.y = mouseUserY - (mouseUserY - vb.y) * factor;
  svg.setAttribute('viewBox', `${vb.x} ${vb.y} ${vb.w} ${vb.h}`);
}

Panning = subtract the dragged delta (converted to user units) from viewBox min-x/min-y. Zooming = scale width/height while pinning the cursor point. vector-effect: non-scaling-stroke keeps borders crisp at any zoom.