Skip to content

Instantly share code, notes, and snippets.

@yongjun21
Created March 10, 2025 05:38
Calculates an ideal viewBox that centers on a target object
/**
* Calculates an ideal viewBox that centers on a target object
* @param objectBBox - Bounding box of the target object
* @param assetWidth - Width of the asset
* @param assetHeight - Height of the asset
* @param targetCoverage - target percentage of the viewport width or height the object should take up
* @param viewportAspectRatio - Aspect ratio of the viewport
* @param minFit - Minimum width and height of the viewport
* @returns - [offsetX, offsetY, viewportWidth, viewportHeight]
*/
export function perfectFit(
objectBBox: [number, number, number, number],
assetWidth: number,
assetHeight: number,
targetCoverage = 0.5,
viewportAspectRatio = assetWidth / assetHeight,
minFit = Math.min(assetWidth, assetHeight, 100)
): [number, number, number, number] {
const sliceAssetWidth = Math.min(
assetHeight * viewportAspectRatio,
assetWidth
);
const sliceAssetHeight = Math.min(
assetWidth / viewportAspectRatio,
assetHeight
);
// target width/height at least minFit and at most slice asset width/height
const targetWidth = Math.min(
Math.max(minFit, (objectBBox[2] - objectBBox[0]) / targetCoverage),
sliceAssetWidth
);
const targetHeight = Math.min(
Math.max(minFit, (objectBBox[3] - objectBBox[1]) / targetCoverage),
sliceAssetHeight
);
// viewport zoom in on target width/height but meets aspect ratio
const viewportWidth = Math.max(
targetHeight * viewportAspectRatio,
targetWidth
);
const viewportHeight = Math.max(
targetWidth / viewportAspectRatio,
targetHeight
);
// offset viewport to center on target
const offsetX = Math.min(
Math.max(0, (objectBBox[0] + objectBBox[2] - viewportWidth) / 2),
assetWidth - viewportWidth
);
const offsetY = Math.min(
Math.max(0, (objectBBox[1] + objectBBox[3] - viewportHeight) / 2),
assetHeight - viewportHeight
);
return [offsetX, offsetY, viewportWidth, viewportHeight];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment