Files
Recordly/src/utils/aspectRatioUtils.ts
T

86 lines
2.6 KiB
TypeScript

export const ASPECT_RATIOS = ['native', '16:9', '9:16', '1:1', '4:3', '4:5', '16:10', '10:16'] as const;
type PresetAspectRatio = typeof ASPECT_RATIOS[number];
type CustomAspectRatio = `${number}:${number}`;
export type AspectRatio = PresetAspectRatio | CustomAspectRatio;
const CUSTOM_ASPECT_RATIO_REGEX = /^(\d+):(\d+)$/;
export function isCustomAspectRatio(aspectRatio: string): aspectRatio is CustomAspectRatio {
if ((ASPECT_RATIOS as readonly string[]).includes(aspectRatio)) {
return false;
}
const match = aspectRatio.match(CUSTOM_ASPECT_RATIO_REGEX);
if (!match) {
return false;
}
const width = Number(match[1]);
const height = Number(match[2]);
return Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0;
}
function parseCustomAspectRatioValue(aspectRatio: string): number | null {
if (!isCustomAspectRatio(aspectRatio)) {
return null;
}
const [widthText, heightText] = aspectRatio.split(':');
const width = Number(widthText);
const height = Number(heightText);
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
return null;
}
return width / height;
}
/**
* Returns the numeric value of an aspect ratio.
* Uses exhaustive type checking to ensure all AspectRatio cases are handled.
* If TypeScript errors here, a new ratio was added to the type but not handled.
*/
export function getAspectRatioValue(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): number {
switch (aspectRatio) {
case 'native': return nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9;
case '16:9': return 16 / 9;
case '9:16': return 9 / 16;
case '1:1': return 1;
case '4:3': return 4 / 3;
case '4:5': return 4 / 5;
case '16:10': return 16 / 10;
case '10:16': return 10 / 16;
default:
return parseCustomAspectRatioValue(aspectRatio) ?? 16 / 9;
}
}
export function getAspectRatioDimensions(
aspectRatio: AspectRatio,
baseWidth: number,
nativeAspectRatio?: number,
): { width: number; height: number } {
const ratio = getAspectRatioValue(aspectRatio, nativeAspectRatio);
return {
width: baseWidth,
height: baseWidth / ratio,
};
}
export function getAspectRatioLabel(aspectRatio: AspectRatio): string {
if (aspectRatio === 'native') {
return 'Native';
}
if (isCustomAspectRatio(aspectRatio)) {
return `Custom ${aspectRatio}`;
}
return aspectRatio;
}
export function formatAspectRatioForCSS(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): string {
if (aspectRatio === 'native') {
return `${nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9}`;
}
return aspectRatio.replace(':', '/');
}