mouse.js (54 lines of code) (raw):

document.addEventListener('DOMContentLoaded', () => { let isMiddleMouseDown = false; let lastX, lastY; let scale = 1; // Current zoom level let translateX = 0, translateY = 0; // Track translation for smooth zooming // Disable default scrolling document.body.style.overflow = 'hidden'; document.addEventListener('mousedown', (e) => { if (e.button === 1 || e.button === 0) { // Middle mouse button is 1 and left is 0 isMiddleMouseDown = true; lastX = e.clientX; lastY = e.clientY; document.body.style.cursor = 'grabbing'; // Change cursor to grabbing hand e.preventDefault(); // Prevent default middle mouse button behavior } }); document.addEventListener('mouseup', (e) => { if (e.button === 1 || e.button === 0) { // Middle mouse button 1 and left is 0 isMiddleMouseDown = false; document.body.style.cursor = 'default'; // Reset cursor } }); document.addEventListener('mousemove', (e) => { if (isMiddleMouseDown) { // Inverted Panning functionality with speed increase based on zoom level let dx = -(e.clientX - lastX); // Invert X movement let dy = -(e.clientY - lastY); // Invert Y movement // Increase panning speed as zoom level increases let speedFactor = 1 + (scale - 1) * 2; // Example: speed doubles when fully zoomed in translateX -= (dx * speedFactor) / scale; translateY -= (dy * speedFactor) / scale; updateTransform(); lastX = e.clientX; lastY = e.clientY; } }); document.addEventListener('wheel', (e) => { e.preventDefault(); // Prevent default scroll behavior let zoomFactor = e.deltaY > 0 ? 0.95 : 1.05; // Zoom in or out // Use cursor position for zooming let cursorX = e.clientX; let cursorY = e.clientY; // Calculate how much the cursor position will shift due to zoom let dx = cursorX - translateX; let dy = cursorY - translateY; // Adjust translation to keep the cursor position fixed during zoom translateX += dx * (1 - zoomFactor); translateY += dy * (1 - zoomFactor); // Zooming logic, maintaining aspect ratio scale *= zoomFactor; scale = Math.max(0.1, Math.min(30, scale)); // Expanded zoom range updateTransform(); }, { passive: false }); function updateTransform() { // Apply scale uniformly in both directions, centered at cursor document.body.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`; // Here, we don't set transformOrigin because it's now based on cursor position dynamically } // Function to update the center after window resize window.addEventListener('resize', () => { updateTransform(); }); // Initial setup for transform origin updateTransform(); });