1export const MIN_SCALE = 0.1;2export const MAX_SCALE = 8;34export function clamp(value, minimum, maximum) {5 return Math.min(Math.max(value, minimum), maximum);6}78export function fitView(viewportWidth, viewportHeight, imageWidth, imageHeight, padding = 32) {9 if (![viewportWidth, viewportHeight, imageWidth, imageHeight].every((value) => Number.isFinite(value) && value > 0)) {10 return {scale: 1, x: 0, y: 0};11 }1213 const availableWidth = Math.max(1, viewportWidth - padding * 2);14 const availableHeight = Math.max(1, viewportHeight - padding * 2);15 const scale = clamp(Math.min(availableWidth / imageWidth, availableHeight / imageHeight), MIN_SCALE, 2);1617 return {18 scale,19 x: (viewportWidth - imageWidth * scale) / 2,20 y: (viewportHeight - imageHeight * scale) / 2,21 };22}2324export function zoomView(view, factor, anchorX, anchorY) {25 const scale = clamp(view.scale * factor, MIN_SCALE, MAX_SCALE);26 const imageX = (anchorX - view.x) / view.scale;27 const imageY = (anchorY - view.y) / view.scale;2829 return {30 scale,31 x: anchorX - imageX * scale,32 y: anchorY - imageY * scale,33 };34}