mirror of
https://github.com/vector-im/element-call.git
synced 2024-11-15 00:04:59 +08:00
Give tiles a minimum area rather than a minimum width and height (#2513)
This seems to result in more sensible cropping and allocation of space across the board, in my testing.
This commit is contained in:
parent
d062871f41
commit
3b38a5322c
@ -93,7 +93,6 @@ export interface GridArrangement {
|
|||||||
columns: number;
|
columns: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tileMinHeight = 130;
|
|
||||||
const tileMaxAspectRatio = 17 / 9;
|
const tileMaxAspectRatio = 17 / 9;
|
||||||
const tileMinAspectRatio = 4 / 3;
|
const tileMinAspectRatio = 4 / 3;
|
||||||
const tileMobileMinAspectRatio = 2 / 3;
|
const tileMobileMinAspectRatio = 2 / 3;
|
||||||
@ -110,11 +109,14 @@ export function arrangeTiles(
|
|||||||
// use of screen space for n tiles without making those tiles too small or
|
// use of screen space for n tiles without making those tiles too small or
|
||||||
// too cropped (having an extreme aspect ratio)
|
// too cropped (having an extreme aspect ratio)
|
||||||
const gap = width < 800 ? 16 : 20;
|
const gap = width < 800 ? 16 : 20;
|
||||||
const tileMinWidth = width < 500 ? 150 : 180;
|
const area = width * minHeight;
|
||||||
|
// Magic numbers that make tiles scale up nicely as the window gets larger
|
||||||
|
const tileArea = Math.pow(Math.sqrt(area) / 8 + 125, 2);
|
||||||
|
const tilesPerPage = Math.min(tileCount, area / tileArea);
|
||||||
|
|
||||||
let columns = Math.min(
|
const columns = Math.min(
|
||||||
// Don't create more columns than we have items for
|
// Don't create more columns than we have items for
|
||||||
tileCount,
|
tilesPerPage,
|
||||||
// The ideal number of columns is given by a packing of equally-sized
|
// The ideal number of columns is given by a packing of equally-sized
|
||||||
// squares into a grid.
|
// squares into a grid.
|
||||||
// width / column = height / row.
|
// width / column = height / row.
|
||||||
@ -122,26 +124,18 @@ export function arrangeTiles(
|
|||||||
// ∴ columns = sqrt(width / height * number of squares).
|
// ∴ columns = sqrt(width / height * number of squares).
|
||||||
// Except we actually want 16:9-ish tiles rather than squares, so we
|
// Except we actually want 16:9-ish tiles rather than squares, so we
|
||||||
// divide the width-to-height ratio by the target aspect ratio.
|
// divide the width-to-height ratio by the target aspect ratio.
|
||||||
Math.ceil(Math.sqrt((width / minHeight / tileMaxAspectRatio) * tileCount)),
|
Math.round(
|
||||||
|
Math.sqrt((width / minHeight / tileMinAspectRatio) * tilesPerPage),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
let rows = Math.ceil(tileCount / columns);
|
let rows = tilesPerPage / columns;
|
||||||
|
// If all the tiles could fit on one page, we want to ensure that they do by
|
||||||
|
// not leaving fractional rows hanging off the bottom
|
||||||
|
if (tilesPerPage === tileCount) rows = Math.ceil(rows);
|
||||||
|
|
||||||
let tileWidth = (width - (columns + 1) * gap) / columns;
|
let tileWidth = (width - (columns + 1) * gap) / columns;
|
||||||
let tileHeight = (minHeight - (rows - 1) * gap) / rows;
|
let tileHeight = (minHeight - (rows - 1) * gap) / rows;
|
||||||
|
|
||||||
// Impose a minimum width and height on the tiles
|
|
||||||
if (tileWidth < tileMinWidth) {
|
|
||||||
// In this case we want the tile width to determine the number of columns,
|
|
||||||
// not the other way around. If we take the above equation for the tile
|
|
||||||
// width (w = (W - (c - 1) * g) / c) and solve for c, we get
|
|
||||||
// c = (W + g) / (w + g).
|
|
||||||
columns = Math.floor((width + gap) / (tileMinWidth + gap));
|
|
||||||
rows = Math.ceil(tileCount / columns);
|
|
||||||
tileWidth = (width - (columns + 1) * gap) / columns;
|
|
||||||
tileHeight = (minHeight - (rows - 1) * gap) / rows;
|
|
||||||
}
|
|
||||||
if (tileHeight < tileMinHeight) tileHeight = tileMinHeight;
|
|
||||||
|
|
||||||
// Impose a minimum and maximum aspect ratio on the tiles
|
// Impose a minimum and maximum aspect ratio on the tiles
|
||||||
const tileAspectRatio = tileWidth / tileHeight;
|
const tileAspectRatio = tileWidth / tileHeight;
|
||||||
// We enforce a different min aspect ratio in 1:1s on mobile
|
// We enforce a different min aspect ratio in 1:1s on mobile
|
||||||
@ -153,7 +147,6 @@ export function arrangeTiles(
|
|||||||
tileWidth = tileHeight * tileMaxAspectRatio;
|
tileWidth = tileHeight * tileMaxAspectRatio;
|
||||||
else if (tileAspectRatio < minAspectRatio)
|
else if (tileAspectRatio < minAspectRatio)
|
||||||
tileHeight = tileWidth / minAspectRatio;
|
tileHeight = tileWidth / minAspectRatio;
|
||||||
// TODO: We might now be hitting the minimum height or width limit again
|
|
||||||
|
|
||||||
return { tileWidth, tileHeight, gap, columns };
|
return { tileWidth, tileHeight, gap, columns };
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,9 @@ export const makeSpotlightPortraitLayout: CallLayout<
|
|||||||
const { width } = useObservableEagerState(minBounds);
|
const { width } = useObservableEagerState(minBounds);
|
||||||
const { gap, tileWidth, tileHeight } = arrangeTiles(
|
const { gap, tileWidth, tileHeight } = arrangeTiles(
|
||||||
width,
|
width,
|
||||||
0,
|
// TODO: We pretend that the minimum height is the width, because the
|
||||||
|
// actual minimum height is difficult to calculate
|
||||||
|
width,
|
||||||
model.grid.length,
|
model.grid.length,
|
||||||
);
|
);
|
||||||
const tileModels: GridTileModel[] = useMemo(
|
const tileModels: GridTileModel[] = useMemo(
|
||||||
|
Loading…
Reference in New Issue
Block a user