42 lines
1.7 KiB
TypeScript
42 lines
1.7 KiB
TypeScript
import { ViewportOffset, CONSTANTS } from '../types';
|
|
import { clamp, calculateDistance } from './math';
|
|
|
|
// Zoom-related functions
|
|
export const calculateZoomDelta = (
|
|
wheelDelta: number,
|
|
accelerationFactor: number,
|
|
baseMultiplier = 0.001
|
|
): number => clamp(wheelDelta * baseMultiplier * accelerationFactor, -0.5, 0.5);
|
|
|
|
export const calculateInitialViewport = (initialZoom: number): ViewportOffset => {
|
|
// When fully zoomed out, we want to see the entire content area
|
|
// The target distribution is sized to match the viewport at minimum zoom
|
|
// Account for the UI exclusion zone at the top
|
|
const windowWidth = window.innerWidth;
|
|
const windowHeight = window.innerHeight;
|
|
|
|
// Same UI margin as in target generation
|
|
const UI_TOP_MARGIN = 100;
|
|
|
|
// Center the viewport on the target area
|
|
const areaWidth = windowWidth / CONSTANTS.ZOOM_LEVELS.min;
|
|
const areaHeight = (windowHeight - UI_TOP_MARGIN) / CONSTANTS.ZOOM_LEVELS.min;
|
|
|
|
// Account for the UI exclusion zone in Y offset
|
|
const startY = UI_TOP_MARGIN / CONSTANTS.ZOOM_LEVELS.min;
|
|
|
|
return {
|
|
x: (areaWidth - windowWidth / initialZoom) / 2,
|
|
y: startY + (areaHeight - windowHeight / initialZoom) / 2
|
|
};
|
|
};
|
|
|
|
export const clampZoom = (zoom: number): number =>
|
|
clamp(zoom, CONSTANTS.ZOOM_LEVELS.min, CONSTANTS.ZOOM_LEVELS.max);
|
|
|
|
// Touch-related functions
|
|
export const calculateTouchDistance = (touch1: React.Touch | Touch, touch2: React.Touch | Touch): number =>
|
|
calculateDistance(touch1.clientX, touch1.clientY, touch2.clientX, touch2.clientY);
|
|
|
|
export const calculateZoomFactor = (currentDistance: number, startDistance: number): number =>
|
|
startDistance > 0 ? currentDistance / startDistance : 1;
|