UNPKG

fit-dimensions

Version:

A tiny utility function to fit a source rectangle within a target rectangle using popular object-fit modes (contain, cover, fill, none, scale-down). Maintains aspect ratio as needed. Useful for images, videos, UI elements, and more.

66 lines (65 loc) 2.44 kB
function isNonNegativeNumber(...args) { return args.every(num => typeof num === 'number' && Number.isFinite(num) && num >= 0); } /** * @description Fit a source rectangle within a target rectangle * * @param srcWidth Source/original width * @param srcHeight Source/original height * @param maxWidth Target width * @param maxHeight Target height * @param mode One of *contain* | *cover* | *fill* | *none* | *scale-down*. (optional) (default: *contain*) * * @returns `{ width: number, height: number, x: number, y: number }` (`x` and `y` are the position used to center the fitted rectangle) * * @see https://github.com/GloryWong/fit-dimensions#readme */ export function fitDimensions(srcWidth, srcHeight, maxWidth, maxHeight, mode = 'contain') { if (!isNonNegativeNumber(srcWidth, srcHeight, maxWidth, maxHeight)) { throw new Error('srcWidth, srcHeight, maxWidth and maxHeight must be non-negative numbers'); } let width = srcWidth; let height = srcHeight; if (width !== 0 && height !== 0) { const scaleX = maxWidth / srcWidth; const scaleY = maxHeight / srcHeight; switch (mode) { case 'contain': { const scale = Math.min(scaleX, scaleY); width = srcWidth * scale; height = srcHeight * scale; break; } case 'cover': { const scale = Math.max(scaleX, scaleY); width = srcWidth * scale; height = srcHeight * scale; break; } case 'fill': { width = maxWidth; height = maxHeight; break; } case 'none': { // Keep original size break; } case 'scale-down': { // Use whichever is smaller: none or contain if (srcWidth > maxWidth || srcHeight > maxHeight) { const scale = Math.min(scaleX, scaleY); width = srcWidth * scale; height = srcHeight * scale; } break; } default: throw new Error(`Unknown mode: ${mode}`); } } // Center the fitted box in the target rectangle const x = (maxWidth - width) / 2; const y = (maxHeight - height) / 2; return { width, height, x, y }; }