PR-C1: adaptive video grid sizing (foundation) #2
1 changed files with 19 additions and 7 deletions
|
|
@ -50,12 +50,22 @@ export type UniformTileGrid = {
|
|||
aspect: number
|
||||
}
|
||||
|
||||
/**
|
||||
/** Numeric lexicographic comparison for scoring arrays. */
|
||||
const compareKeys = (a: number[], b: number[]): number => {
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return a[i] - b[i]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick the column count that best fills the viewport. Prioritises:
|
||||
* 1. No vertical overflow (avoids unnecessary scroll)
|
||||
* 2. Minimal leftover whitespace (h-pad + v-pad)
|
||||
* 3. Aspect ratio closest to 16:9
|
||||
* 4. Larger tiles
|
||||
* 2. No horizontal overflow (avoids sideways clip/scroll)
|
||||
* 3. Minimal leftover whitespace (h-pad + v-pad)
|
||||
* 4. Aspect ratio closest to 16:9
|
||||
* 5. Larger tiles
|
||||
*/
|
||||
export const computeUniformGrid = (
|
||||
tileCount: number,
|
||||
|
|
@ -83,9 +93,9 @@ export const computeUniformGrid = (
|
|||
tileW = widthLimit
|
||||
tileH = widthLimit / TILE_ASPECT_MAX
|
||||
} else if (fillAspect < TILE_ASPECT_MIN) {
|
||||
// Too tall: cap at 3:4, tiles narrower than full width -> h-pad
|
||||
tileH = rowH
|
||||
tileW = rowH * TILE_ASPECT_MIN
|
||||
// Too tall: cap at 3:4, tiles shorter than row -> v-pad (letterbox)
|
||||
tileW = widthLimit
|
||||
tileH = widthLimit / TILE_ASPECT_MIN
|
||||
} else {
|
||||
// In range: fills both dims exactly
|
||||
tileW = widthLimit
|
||||
|
|
@ -95,15 +105,17 @@ export const computeUniformGrid = (
|
|||
const bboxW = cols * tileW + (cols - 1) * TILE_GAP
|
||||
const bboxH = rows * tileH + (rows - 1) * TILE_GAP
|
||||
const vOverflow = Math.max(0, bboxH - ch)
|
||||
const hOverflow = Math.max(0, bboxW - cw)
|
||||
const waste = Math.max(0, cw - bboxW) + Math.max(0, ch - bboxH)
|
||||
const key = [
|
||||
Math.round(vOverflow),
|
||||
Math.round(hOverflow),
|
||||
Math.round(waste),
|
||||
Number(Math.abs(aspect - TILE_ASPECT_MAX).toFixed(3)),
|
||||
-Math.round(tileW * tileH),
|
||||
]
|
||||
|
||||
if (!bestKey || key < bestKey) {
|
||||
if (!bestKey || compareKeys(key, bestKey) < 0) {
|
||||
bestKey = key
|
||||
best = {cols, rows, tileWidth: tileW, tileHeight: tileH, aspect}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue