UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

97 lines (96 loc) 3.84 kB
const DEFAULT_RUBBER_BAND_FACTOR = .15; const WHEEL_ZOOM_SENSITIVITY = .002; const normalizeRotation = (degrees) => (degrees % 360 + 360) % 360; const effectiveSize = (natural, rotate) => rotate === 90 || rotate === 270 ? { height: natural.width, width: natural.height } : natural; const computeFit = (natural, viewport, rotate, fillViewport = false) => { const effective = effectiveSize(natural, rotate); const availableWidth = Math.max(viewport.width - 48, 0); const availableHeight = Math.max(viewport.height - 48, 0); const containScale = Math.min(availableWidth / effective.width, availableHeight / effective.height, ...fillViewport ? [] : [1]); const width = effective.width * containScale; const height = effective.height * containScale; return { height, width, x: (viewport.width - width) / 2, y: (viewport.height - height) / 2 }; }; const unrotatedRect = (fit, rotate) => { if (rotate !== 90 && rotate !== 270) return fit; const centerX = fit.x + fit.width / 2; const centerY = fit.y + fit.height / 2; return { height: fit.width, width: fit.height, x: centerX - fit.height / 2, y: centerY - fit.width / 2 }; }; const anchoredZoom = (current, targetScale, anchor, fitRect) => { const centerX = fitRect.x + fitRect.width / 2; const centerY = fitRect.y + fitRect.height / 2; const ratio = targetScale / current.scale; return { scale: targetScale, x: anchor.x - centerX - ratio * (anchor.x - centerX - current.x), y: anchor.y - centerY - ratio * (anchor.y - centerY - current.y) }; }; const panBounds = (state, fitRect, viewport) => { const centerX = fitRect.x + fitRect.width / 2; const centerY = fitRect.y + fitRect.height / 2; const scaledWidth = fitRect.width * state.scale; const scaledHeight = fitRect.height * state.scale; const axis = (center, scaledSize, viewportSize) => { if (scaledSize - viewportSize <= 0) return { max: 0, min: 0 }; return { max: scaledSize / 2 - center, min: viewportSize - center - scaledSize / 2 }; }; return { x: axis(centerX, scaledWidth, viewport.width), y: axis(centerY, scaledHeight, viewport.height) }; }; const clampPan = (state, fitRect, viewport) => { const bounds = panBounds(state, fitRect, viewport); return { x: Math.min(Math.max(state.x, bounds.x.min), bounds.x.max), y: Math.min(Math.max(state.y, bounds.y.min), bounds.y.max) }; }; const rubberBand = (value, min, max, factor = DEFAULT_RUBBER_BAND_FACTOR) => { if (value < min) return min - (min - value) * factor; if (value > max) return max + (value - max) * factor; return value; }; const clampScale = (scale, maxScale = 8) => Math.min(Math.max(scale, 1), maxScale); const wheelZoomFactor = (deltaY) => Math.exp(-deltaY * WHEEL_ZOOM_SENSITIVITY); const normalizeWheelDelta = (deltaY, deltaMode = 0, viewportHeight = 0) => { if (deltaMode === 1) return deltaY * 16; if (deltaMode === 2) return deltaY * (viewportHeight || 640); return deltaY; }; const naturalScale = (natural, fitRect, rotate) => effectiveSize(natural, rotate).width / fitRect.width; const resolveInitialScale = (policy, natural, fitRect, rotate, threshold = 2) => { if (policy === "fit") return 1; const target = naturalScale(natural, fitRect, rotate); if (!Number.isFinite(target) || target <= 0) return 1; if (policy === "auto" && target > threshold) return 1; return Math.max(1, target); }; const doubleClickTarget = (currentScale, natural, fitRect, rotate) => { if (currentScale > 1) return 1; return Math.max(2, naturalScale(natural, fitRect, rotate)); }; //#endregion export { DEFAULT_RUBBER_BAND_FACTOR, WHEEL_ZOOM_SENSITIVITY, anchoredZoom, clampPan, clampScale, computeFit, doubleClickTarget, naturalScale, normalizeRotation, normalizeWheelDelta, panBounds, resolveInitialScale, rubberBand, unrotatedRect, wheelZoomFactor }; //# sourceMappingURL=geometry.mjs.map