Zooms and pans interactive canvas content
by Rajesh Danabal
HTML
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #ccc;"></canvas>
<button onclick="resetZoomPan()">Reset Zoom/Pan</button>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let scale = 1;
let offsetX = 0;
let offsetY = 0;
let targetScale = scale;
let targetOffsetX = offsetX;
let targetOffsetY = offsetY;
let animationFrame = null;
function lerp(a, b, t) {
return a + (b - a) * t;
}
function animateViewportTransition() {
if (animationFrame) cancelAnimationFrame(animationFrame);
const duration = 400;
const startTime = performance.now();
const startScale = scale;
const startOffsetX = offsetX;
const startOffsetY = offsetY;
function animate() {
const now = performance.now();
const t = Math.min(1, (now - startTime) / duration);
const eased = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
scale = lerp(startScale, targetScale, eased);
offsetX = lerp(startOffsetX, targetOffsetX, eased);
offsetY = lerp(startOffsetY, targetOffsetY, eased);
render();
if (t < 1) {
animationFrame = requestAnimationFrame(animate);
} else {
animationFrame = null;
}
}
animationFrame = requestAnimationFrame(animate);
}
function zoomTo(scaleValue, centerX, centerY) {
const worldX = (centerX - offsetX) / scale;
const worldY = (centerY - offsetY) / scale;
targetScale = scaleValue;
targetOffsetX = centerX - worldX * scaleValue;
targetOffsetY = centerY - worldY * scaleValue;
animateViewportTransition();
}
function panTo(x, y) {
targetOffsetX = x;
targetOffsetY = y;
targetScale = scale;
animateViewportTransition();
}
function resetZoomPan() {
targetScale = 1;
targetOffsetX = 0;
targetOffsetY = 0;
animateViewportTransition();
}
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
...