The <video> element used `max-w-full max-h-full`, which only ever shrinks oversized media. A source smaller than the window (480p on a 1080p display) rendered at its intrinsic size — a small picture floating in a black frame. Fill the container and let `object-contain` do the scaling, so the picture fits whichever axis constrains it in both directions while preserving aspect ratio. The sizing rules move to `videoFit.ts` so they are unit-testable outside the component.
50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
// Sizing rules for the HTML5 <video> element in the full-screen player.
|
|
// Extracted from VideoPlayer.svelte so the fit behaviour is unit-testable.
|
|
|
|
/**
|
|
* Classes applied to the <video> element so it fits the player viewport.
|
|
*
|
|
* TRACES: UR-005
|
|
*
|
|
* `max-w-full max-h-full` only ever *shrinks* oversized media, so a source
|
|
* smaller than the window (e.g. 480p on a 1080p display) rendered at its
|
|
* intrinsic size - a small box in the middle of a black screen. Filling the
|
|
* container and letting `object-contain` do the scaling fits the picture to
|
|
* whichever axis constrains it, in both directions, preserving aspect ratio.
|
|
*/
|
|
export function videoFitClass(): string {
|
|
return "w-full h-full object-contain";
|
|
}
|
|
|
|
export interface FittedSize {
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
/**
|
|
* The rendered size of a video of the given intrinsic dimensions once it has
|
|
* been fitted into the container - i.e. scaled (up or down) so that it touches
|
|
* the container on its constraining axis, with the other axis letter/pillar
|
|
* boxed. Mirrors what `object-fit: contain` on a full-size element does.
|
|
*/
|
|
export function fittedVideoSize(
|
|
intrinsicWidth: number,
|
|
intrinsicHeight: number,
|
|
containerWidth: number,
|
|
containerHeight: number,
|
|
): FittedSize {
|
|
if (intrinsicWidth <= 0 || intrinsicHeight <= 0) {
|
|
return { width: 0, height: 0 };
|
|
}
|
|
|
|
const scale = Math.min(
|
|
containerWidth / intrinsicWidth,
|
|
containerHeight / intrinsicHeight,
|
|
);
|
|
|
|
return {
|
|
width: intrinsicWidth * scale,
|
|
height: intrinsicHeight * scale,
|
|
};
|
|
}
|