fix(album): keep true aspect ratios for two-image layouts

Split clampRatio into a sanity-check helper (safeRatio: reject
zero / NaN / negatives) and the actual aspect clamp. Two-image
albums now keep each image's real ratio so the cells match the
images exactly with no object-cover cropping. Three-plus image
layouts still clamp ratios to a 0.55-2 band so a single extreme
image cannot warp the mosaic.
This commit is contained in:
TerryM
2026-05-30 02:25:01 +08:00
parent 8646b51b6c
commit 27f9dbbc45

View File

@@ -34,8 +34,13 @@ export type AlbumLayout = {
* Keep ratios within a sane range so one extreme image can't make the whole * Keep ratios within a sane range so one extreme image can't make the whole
* mosaic absurdly tall or flat. Beyond this the cell crops (object-cover). * mosaic absurdly tall or flat. Beyond this the cell crops (object-cover).
*/ */
function clampRatio(ratio: number | undefined): number { function safeRatio(ratio: number | undefined): number {
if (!ratio || !Number.isFinite(ratio) || ratio <= 0) return 1; if (!ratio || !Number.isFinite(ratio) || ratio <= 0) return 1;
return ratio;
}
/** Bound a ratio so one extreme image can't make a multi-image mosaic ugly. */
function clampRatio(ratio: number): number {
return Math.min(2, Math.max(0.55, ratio)); return Math.min(2, Math.max(0.55, ratio));
} }
@@ -116,8 +121,11 @@ function layoutPrimaryPlusLine(ratios: number[]): AlbumLayout {
export function computeAlbumLayout( export function computeAlbumLayout(
rawRatios: (number | undefined)[], rawRatios: (number | undefined)[],
): AlbumLayout | null { ): AlbumLayout | null {
const ratios = rawRatios.map(clampRatio); const ratios = rawRatios.map(safeRatio);
if (ratios.length < 2) return null; if (ratios.length < 2) return null;
// Two images keep their true ratios so each cell matches its image exactly
// (object-cover then fits with no cropping). 3+ are clamped to keep the
// mosaic tidy.
if (ratios.length === 2) return layoutTwo(ratios); if (ratios.length === 2) return layoutTwo(ratios);
return layoutPrimaryPlusLine(ratios); return layoutPrimaryPlusLine(ratios.map(clampRatio));
} }