svelte-image-viewer
Version:
A couple of simple components for displaying content with pan and zoom capabilities.
46 lines (45 loc) • 1.63 kB
JavaScript
/**
* Calculates the target viewer state needed to fit an element inside its parent container.
*
* @param element - The element to measure against its parent
* @param currentScale - The element's current viewer scale
* @returns Target offsets and scale for the viewer components
*/
export function scaleToFit(element, currentScale) {
const parent = element.parentElement;
if (parent === null) {
return getDefaultTargets();
}
const elementRect = element.getBoundingClientRect();
const parentRect = parent.getBoundingClientRect();
if (elementRect.width === 0 ||
elementRect.height === 0 ||
parentRect.width === 0 ||
parentRect.height === 0) {
return getDefaultTargets();
}
const normalisedCurrentScale = normaliseCurrentScale(currentScale);
return {
targetOffsetX: 0,
targetOffsetY: 0,
targetScale: getScale(elementRect, parentRect, normalisedCurrentScale),
};
}
function getScale(elementRect, parentRect, currentScale) {
const baseWidth = elementRect.width / currentScale;
const baseHeight = elementRect.height / currentScale;
const widthScale = parentRect.width / baseWidth;
const heightScale = parentRect.height / baseHeight;
const scale = Math.min(widthScale, heightScale);
return Number.isFinite(scale) && scale > 0 ? scale : 1;
}
function normaliseCurrentScale(currentScale) {
return Number.isFinite(currentScale) && currentScale > 0 ? currentScale : 1;
}
function getDefaultTargets() {
return {
targetOffsetX: 0,
targetOffsetY: 0,
targetScale: 1,
};
}