Sub grid layout refactor
This commit is contained in:
parent
c094e820d1
commit
e7a2c500a0
1 changed files with 288 additions and 335 deletions
|
@ -36,7 +36,12 @@ function isInside([x, y], targetTile) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTilePositions(tileCount, gridBounds, presenterTileCount) {
|
function getTilePositions(
|
||||||
|
tileCount,
|
||||||
|
presenterTileCount,
|
||||||
|
gridWidth,
|
||||||
|
gridHeight
|
||||||
|
) {
|
||||||
if (tileCount === 0) {
|
if (tileCount === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -49,196 +54,169 @@ function getTilePositions(tileCount, gridBounds, presenterTileCount) {
|
||||||
console.warn("Over 3 presenters is not currently supported");
|
console.warn("Over 3 presenters is not currently supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridWidth = gridBounds.width;
|
const gap = 8;
|
||||||
const gridHeight = gridBounds.height;
|
|
||||||
|
const { layoutDirection, participantGridRatio } = getGridLayout(
|
||||||
|
tileCount,
|
||||||
|
presenterTileCount,
|
||||||
|
gridWidth,
|
||||||
|
gridHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
let participantGridWidth, participantGridHeight;
|
||||||
|
|
||||||
|
if (layoutDirection === "vertical") {
|
||||||
|
participantGridWidth = gridWidth;
|
||||||
|
participantGridHeight = Math.round(gridHeight * participantGridRatio);
|
||||||
|
} else {
|
||||||
|
participantGridWidth = Math.round(gridWidth * participantGridRatio);
|
||||||
|
participantGridHeight = gridHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const participantGridPositions = getSubGridPositions(
|
||||||
|
tileCount - presenterTileCount,
|
||||||
|
participantGridWidth,
|
||||||
|
participantGridHeight,
|
||||||
|
gap
|
||||||
|
);
|
||||||
|
const participantGridBounds = getSubGridBoundingBox(participantGridPositions);
|
||||||
|
|
||||||
|
let presenterGridWidth, presenterGridHeight;
|
||||||
|
|
||||||
|
if (layoutDirection === "vertical") {
|
||||||
|
presenterGridWidth = gridWidth;
|
||||||
|
presenterGridHeight = gridHeight - participantGridBounds.height;
|
||||||
|
} else {
|
||||||
|
presenterGridWidth = gridWidth - participantGridBounds.width;
|
||||||
|
presenterGridHeight = gridHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const presenterGridPositions = getSubGridPositions(
|
||||||
|
presenterTileCount,
|
||||||
|
presenterGridWidth,
|
||||||
|
presenterGridHeight,
|
||||||
|
gap
|
||||||
|
);
|
||||||
|
const presenterGridBounds = getSubGridBoundingBox(presenterGridPositions);
|
||||||
|
|
||||||
|
if (layoutDirection === "vertical") {
|
||||||
|
centerTiles(
|
||||||
|
participantGridPositions,
|
||||||
|
gridWidth,
|
||||||
|
presenterGridBounds.height
|
||||||
|
);
|
||||||
|
applyTileOffsets(
|
||||||
|
participantGridPositions,
|
||||||
|
0,
|
||||||
|
presenterGridBounds.height + gap
|
||||||
|
);
|
||||||
|
centerTiles(presenterGridPositions, gridWidth, presenterGridBounds.height);
|
||||||
|
} else {
|
||||||
|
applyTileOffsets(
|
||||||
|
participantGridPositions,
|
||||||
|
presenterGridBounds.width + gap,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
centerTiles(presenterGridPositions, presenterGridBounds.width, gridHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tilePositions = [
|
||||||
|
...presenterGridPositions,
|
||||||
|
...participantGridPositions,
|
||||||
|
];
|
||||||
|
|
||||||
|
centerTiles(tilePositions, gridWidth, gridHeight);
|
||||||
|
|
||||||
|
return tilePositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubGridBoundingBox(positions) {
|
||||||
|
let left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < positions.length; i++) {
|
||||||
|
const { x, y, width, height } = positions[i];
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
left = x;
|
||||||
|
right = x + width;
|
||||||
|
top = y;
|
||||||
|
bottom = y + height;
|
||||||
|
} else {
|
||||||
|
if (x < left) {
|
||||||
|
left = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < top) {
|
||||||
|
top = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x + width > right) {
|
||||||
|
right = x + width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y + height > bottom) {
|
||||||
|
bottom = y + height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
width: right - left,
|
||||||
|
height: bottom - top,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGridLayout(tileCount, presenterTileCount, gridWidth, gridHeight) {
|
||||||
|
let layoutDirection = "horizontal";
|
||||||
|
let participantGridRatio = 1;
|
||||||
|
|
||||||
|
if (presenterTileCount === 0) {
|
||||||
|
return { participantGridRatio, layoutDirection };
|
||||||
|
}
|
||||||
|
|
||||||
const gridAspectRatio = gridWidth / gridHeight;
|
const gridAspectRatio = gridWidth / gridHeight;
|
||||||
|
|
||||||
if (presenterTileCount) {
|
if (gridAspectRatio < 1) {
|
||||||
const subGridTileCount = tileCount - presenterTileCount;
|
layoutDirection = "vertical";
|
||||||
|
participantGridRatio = 1 / 3;
|
||||||
let presenterGridWidth,
|
|
||||||
presenterGridHeight,
|
|
||||||
presenterColumnCount,
|
|
||||||
presenterRowCount,
|
|
||||||
presenterTileAspectRatio;
|
|
||||||
|
|
||||||
let subGridWidth,
|
|
||||||
subGridHeight,
|
|
||||||
subGridOffsetLeft,
|
|
||||||
subGridOffsetTop,
|
|
||||||
subGridColumnCount,
|
|
||||||
subGridRowCount,
|
|
||||||
subGridTileAspectRatio;
|
|
||||||
|
|
||||||
if (gridAspectRatio < 3 / 4) {
|
|
||||||
// Phone
|
|
||||||
presenterGridWidth = gridWidth;
|
|
||||||
presenterColumnCount = 1;
|
|
||||||
presenterRowCount = presenterTileCount;
|
|
||||||
presenterTileAspectRatio = 16 / 9;
|
|
||||||
subGridTileAspectRatio = 16 / 9;
|
|
||||||
|
|
||||||
if (presenterTileCount > 2) {
|
|
||||||
presenterColumnCount = 2;
|
|
||||||
presenterRowCount = 2;
|
|
||||||
presenterTileAspectRatio = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subGridTileCount < 3) {
|
|
||||||
if (presenterTileCount === 1) {
|
|
||||||
}
|
|
||||||
subGridColumnCount = presenterTileCount === 1 ? 1 : subGridTileCount;
|
|
||||||
subGridRowCount = presenterTileCount === 1 ? subGridTileCount : 1;
|
|
||||||
subGridTileAspectRatio = presenterTileCount === 1 ? 16 / 9 : 0;
|
|
||||||
} else if (subGridTileCount < 5) {
|
|
||||||
subGridColumnCount = 2;
|
|
||||||
subGridRowCount = 2;
|
|
||||||
} else if (subGridTileCount < 7) {
|
|
||||||
subGridColumnCount = 2;
|
|
||||||
subGridRowCount = 3;
|
|
||||||
} else if (subGridTileCount < 10) {
|
|
||||||
subGridColumnCount = 3;
|
|
||||||
subGridRowCount = 3;
|
|
||||||
} else {
|
} else {
|
||||||
subGridColumnCount = 4;
|
layoutDirection = "horizontal";
|
||||||
subGridRowCount = 3;
|
participantGridRatio = 1 / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
presenterGridHeight = Math.round(
|
return { participantGridRatio, layoutDirection };
|
||||||
gridHeight *
|
|
||||||
(1 -
|
|
||||||
1 /
|
|
||||||
Math.max(
|
|
||||||
presenterRowCount + 2 - Math.max(subGridRowCount - 1, 0),
|
|
||||||
2
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
subGridWidth = gridWidth;
|
|
||||||
subGridHeight = gridHeight - presenterGridHeight;
|
|
||||||
subGridOffsetTop = presenterGridHeight;
|
|
||||||
subGridOffsetLeft = 0;
|
|
||||||
} else if (gridAspectRatio < 1) {
|
|
||||||
// Tablet
|
|
||||||
presenterGridWidth = gridWidth;
|
|
||||||
presenterColumnCount = 1;
|
|
||||||
presenterRowCount = presenterTileCount;
|
|
||||||
presenterTileAspectRatio = 16 / 9;
|
|
||||||
subGridTileAspectRatio = 16 / 9;
|
|
||||||
|
|
||||||
if (presenterTileCount > 2) {
|
|
||||||
presenterColumnCount = 2;
|
|
||||||
presenterRowCount = 2;
|
|
||||||
presenterTileAspectRatio = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subGridTileCount < 3) {
|
function centerTiles(positions, gridWidth, gridHeight) {
|
||||||
if (presenterTileCount === 1) {
|
const bounds = getSubGridBoundingBox(positions);
|
||||||
}
|
|
||||||
subGridColumnCount = presenterTileCount === 1 ? 1 : subGridTileCount;
|
const leftOffset = Math.round((gridWidth - bounds.width) / 2);
|
||||||
subGridRowCount = presenterTileCount === 1 ? subGridTileCount : 1;
|
const topOffset = Math.round((gridHeight - bounds.height) / 2);
|
||||||
subGridTileAspectRatio = presenterTileCount === 1 ? 16 / 9 : 0;
|
|
||||||
} else if (subGridTileCount < 5) {
|
applyTileOffsets(positions, leftOffset, topOffset);
|
||||||
subGridColumnCount = 2;
|
|
||||||
subGridRowCount = 2;
|
return positions;
|
||||||
} else if (subGridTileCount < 7) {
|
|
||||||
subGridColumnCount = 2;
|
|
||||||
subGridRowCount = 3;
|
|
||||||
} else if (subGridTileCount < 10) {
|
|
||||||
subGridColumnCount = 3;
|
|
||||||
subGridRowCount = 3;
|
|
||||||
} else {
|
|
||||||
subGridColumnCount = 4;
|
|
||||||
subGridRowCount = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
presenterGridHeight = Math.round(
|
function applyTileOffsets(positions, leftOffset, topOffset) {
|
||||||
gridHeight *
|
for (const position of positions) {
|
||||||
(1 -
|
position.x += leftOffset;
|
||||||
1 /
|
position.y += topOffset;
|
||||||
Math.max(
|
|
||||||
presenterRowCount + 2 - Math.max(subGridRowCount - 1, 0),
|
|
||||||
2
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
subGridWidth = gridWidth;
|
|
||||||
subGridHeight = gridHeight - presenterGridHeight;
|
|
||||||
subGridOffsetTop = presenterGridHeight;
|
|
||||||
subGridOffsetLeft = 0;
|
|
||||||
} else if (gridAspectRatio < 17 / 9) {
|
|
||||||
// Computer
|
|
||||||
presenterGridWidth = gridWidth * (2 / 3);
|
|
||||||
presenterGridHeight = gridHeight;
|
|
||||||
presenterColumnCount = 1;
|
|
||||||
presenterRowCount = presenterTileCount;
|
|
||||||
presenterTileAspectRatio = 0;
|
|
||||||
|
|
||||||
subGridWidth = gridWidth - presenterGridWidth;
|
|
||||||
subGridHeight = gridHeight;
|
|
||||||
subGridColumnCount = Math.ceil(subGridTileCount / 6);
|
|
||||||
subGridRowCount = Math.ceil(subGridTileCount / subGridColumnCount);
|
|
||||||
subGridOffsetTop = 0;
|
|
||||||
subGridOffsetLeft = presenterGridWidth;
|
|
||||||
subGridTileAspectRatio = 16 / 9;
|
|
||||||
} else if (gridAspectRatio <= 32 / 9) {
|
|
||||||
// Ultrawide
|
|
||||||
presenterGridWidth = gridWidth * (2 / 3);
|
|
||||||
presenterGridHeight = gridHeight;
|
|
||||||
presenterColumnCount = 1;
|
|
||||||
presenterRowCount = presenterTileCount;
|
|
||||||
presenterTileAspectRatio = 16 / 9;
|
|
||||||
|
|
||||||
subGridWidth = gridWidth - presenterGridWidth;
|
|
||||||
subGridHeight = gridHeight;
|
|
||||||
subGridColumnCount = Math.ceil(subGridTileCount / 4);
|
|
||||||
subGridRowCount = Math.ceil(subGridTileCount / subGridColumnCount);
|
|
||||||
subGridOffsetTop = 0;
|
|
||||||
subGridOffsetLeft = presenterGridWidth;
|
|
||||||
subGridTileAspectRatio = 16 / 9;
|
|
||||||
} else {
|
|
||||||
// Super Ultrawide
|
|
||||||
presenterGridWidth = gridWidth * (2 / 3);
|
|
||||||
presenterGridHeight = gridHeight;
|
|
||||||
presenterColumnCount = 1;
|
|
||||||
presenterRowCount = presenterTileCount;
|
|
||||||
presenterTileAspectRatio = 16 / 9;
|
|
||||||
|
|
||||||
subGridWidth = gridWidth - presenterGridWidth;
|
|
||||||
subGridHeight = gridHeight;
|
|
||||||
subGridColumnCount = Math.ceil(subGridTileCount / 3);
|
|
||||||
subGridRowCount = Math.ceil(subGridTileCount / subGridColumnCount);
|
|
||||||
subGridOffsetTop = 0;
|
|
||||||
subGridOffsetLeft = presenterGridWidth;
|
|
||||||
subGridTileAspectRatio = 16 / 9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const presenterPositions = getSubGridPositions(
|
return positions;
|
||||||
presenterTileCount,
|
|
||||||
presenterColumnCount,
|
|
||||||
presenterRowCount,
|
|
||||||
presenterTileAspectRatio,
|
|
||||||
{
|
|
||||||
width: presenterGridWidth,
|
|
||||||
height: presenterGridHeight,
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
const subGridPositions = getSubGridPositions(
|
function getSubGridLayout(tileCount, gridWidth, gridHeight) {
|
||||||
subGridTileCount,
|
const gridAspectRatio = gridWidth / gridHeight;
|
||||||
subGridColumnCount,
|
|
||||||
subGridRowCount,
|
|
||||||
subGridTileAspectRatio,
|
|
||||||
{
|
|
||||||
width: subGridWidth,
|
|
||||||
height: subGridHeight,
|
|
||||||
offsetTop: subGridOffsetTop,
|
|
||||||
offsetLeft: subGridOffsetLeft,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return [...presenterPositions, ...subGridPositions];
|
|
||||||
} else {
|
|
||||||
let columnCount, rowCount;
|
let columnCount, rowCount;
|
||||||
let tileAspectRatio = 16 / 9;
|
let tileAspectRatio = 16 / 9;
|
||||||
|
|
||||||
|
@ -342,33 +320,21 @@ function getTilePositions(tileCount, gridBounds, presenterTileCount) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSubGridPositions(
|
return { columnCount, rowCount, tileAspectRatio };
|
||||||
tileCount,
|
|
||||||
columnCount,
|
|
||||||
rowCount,
|
|
||||||
tileAspectRatio,
|
|
||||||
gridBounds
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubGridPositions(
|
function getSubGridPositions(tileCount, gridWidth, gridHeight, gap) {
|
||||||
tileCount,
|
|
||||||
columnCount,
|
|
||||||
rowCount,
|
|
||||||
tileAspectRatio,
|
|
||||||
gridBounds
|
|
||||||
) {
|
|
||||||
if (tileCount === 0) {
|
if (tileCount === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { columnCount, rowCount, tileAspectRatio } = getSubGridLayout(
|
||||||
|
tileCount,
|
||||||
|
gridWidth,
|
||||||
|
gridHeight
|
||||||
|
);
|
||||||
|
|
||||||
const newTilePositions = [];
|
const newTilePositions = [];
|
||||||
const gridWidth = gridBounds.width;
|
|
||||||
const gridHeight = gridBounds.height;
|
|
||||||
const gridOffsetLeft = gridBounds.offsetLeft || 0;
|
|
||||||
const gridOffsetTop = gridBounds.offsetTop || 0;
|
|
||||||
const gap = 8;
|
|
||||||
|
|
||||||
const boxWidth = Math.round(
|
const boxWidth = Math.round(
|
||||||
(gridWidth - gap * (columnCount + 1)) / columnCount
|
(gridWidth - gap * (columnCount + 1)) / columnCount
|
||||||
|
@ -392,19 +358,9 @@ function getSubGridPositions(
|
||||||
tileHeight = boxHeight;
|
tileHeight = boxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
const paddingTop =
|
|
||||||
(gridHeight - tileHeight * rowCount - gap * (rowCount - 1)) / 2;
|
|
||||||
|
|
||||||
const paddingLeft =
|
|
||||||
(gridWidth - tileWidth * columnCount - gap * (columnCount - 1)) / 2;
|
|
||||||
|
|
||||||
for (let i = 0; i < tileCount; i++) {
|
for (let i = 0; i < tileCount; i++) {
|
||||||
const verticalIndex = Math.floor(i / columnCount);
|
const verticalIndex = Math.floor(i / columnCount);
|
||||||
const top =
|
const top = verticalIndex * gap + verticalIndex * tileHeight;
|
||||||
gridOffsetTop +
|
|
||||||
verticalIndex * tileHeight +
|
|
||||||
verticalIndex * gap +
|
|
||||||
paddingTop;
|
|
||||||
|
|
||||||
let rowItemCount;
|
let rowItemCount;
|
||||||
|
|
||||||
|
@ -419,21 +375,15 @@ function getSubGridPositions(
|
||||||
let centeringPadding = 0;
|
let centeringPadding = 0;
|
||||||
|
|
||||||
if (rowItemCount < columnCount) {
|
if (rowItemCount < columnCount) {
|
||||||
|
const subgridWidth = tileWidth * columnCount + (gap * columnCount - 1);
|
||||||
centeringPadding = Math.round(
|
centeringPadding = Math.round(
|
||||||
(gridWidth -
|
(subgridWidth - (tileWidth * rowItemCount + (gap * rowItemCount - 1))) /
|
||||||
(tileWidth * rowItemCount +
|
|
||||||
(gap * rowItemCount - 1) +
|
|
||||||
paddingLeft * 2)) /
|
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const left =
|
const left =
|
||||||
gridOffsetLeft +
|
centeringPadding + gap * horizontalIndex + tileWidth * horizontalIndex;
|
||||||
paddingLeft +
|
|
||||||
centeringPadding +
|
|
||||||
gap * horizontalIndex +
|
|
||||||
tileWidth * horizontalIndex;
|
|
||||||
|
|
||||||
newTilePositions.push({
|
newTilePositions.push({
|
||||||
width: tileWidth,
|
width: tileWidth,
|
||||||
|
@ -522,8 +472,9 @@ export function VideoGrid({ participants }) {
|
||||||
tiles: newTiles,
|
tiles: newTiles,
|
||||||
tilePositions: getTilePositions(
|
tilePositions: getTilePositions(
|
||||||
newTiles.length,
|
newTiles.length,
|
||||||
gridBounds,
|
presenterTileCount,
|
||||||
presenterTileCount
|
gridBounds.width,
|
||||||
|
gridBounds.height
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -534,8 +485,9 @@ export function VideoGrid({ participants }) {
|
||||||
tiles: newTiles,
|
tiles: newTiles,
|
||||||
tilePositions: getTilePositions(
|
tilePositions: getTilePositions(
|
||||||
newTiles.length,
|
newTiles.length,
|
||||||
gridBounds,
|
presenterTileCount,
|
||||||
presenterTileCount
|
gridBounds.width,
|
||||||
|
gridBounds.height
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -677,8 +629,9 @@ export function VideoGrid({ participants }) {
|
||||||
tiles: newTiles,
|
tiles: newTiles,
|
||||||
tilePositions: getTilePositions(
|
tilePositions: getTilePositions(
|
||||||
newTiles.length,
|
newTiles.length,
|
||||||
gridBounds,
|
presenterTileCount,
|
||||||
presenterTileCount
|
gridBounds.width,
|
||||||
|
gridBounds.height
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue