7. Сложная композиция сцены остаётся в игровых компонентах
Некоторым сценам нужно больше, чем центрирование и масштабирование. В сцене предмета есть альбом, заголовок, индикатор прогресса и кнопки.
ItemSceneLayoutComponent описывает композицию:
private applyLayout(): void {
const orientation = this.node.screen.getOrientation();
const screen = this.node.screen.getVirtualSize();
this.applyButtonScale(orientation);
this.positionAlbumStage(screen.width, screen.height, orientation);
this.sizeTitleCover(screen.width);
this.sizeAlbumProgress();
this.positionAlbumProgress();
this.positionTitle();
this.positionPlayButton(screen.height);
this.positionAlbumsButton(screen.height);
}
Размер альбома определяется разными осями:
const targetScale = orientation === 'port'
? (screenWidth * this.config.portImageWidthScreenPercent) / frameWidth
: (screenHeight * this.config.landImageHeightScreenPercent) / frameHeight;
albumStage.setScale(targetScale, targetScale);
albumStage.setPosition(Math.round(screenWidth / 2), Math.round(screenHeight / 2));
В вертикальной ориентации важнее ширина, в горизонтальной — высота.
JSON-вёрстка предоставляет это как конфигурацию:
{
"landImageHeightScreenPercent": 0.6,
"portImageWidthScreenPercent": 0.6,
"landPlayButtonScale": 1,
"portPlayButtonScale": 1
}
Это адаптивная компоновка, а не просто изменение масштаба.
8. Сетка каталога: разное число столбцов для разных ориентаций
Сцена предметов меняет сетку каталога альбомов:
- горизонтальная ориентация: 5 столбцов;
- вертикальная ориентация: 2 столбца.
Конфигурация:
{
"itemsAlbumsGrid": {
"type": "ItemsAlbumsGridComponent",
"enabled": true,
"data": {
"landColumns": 5,
"portColumns": 2,
"horizontalPaddingPx": 48,
"bottomPaddingPx": 48,
"columnGapPx": 28,
"rowGapPx": 28,
"maxScale": 1
}
}
}
Код:
private resolveColumns(): number {
return this.node.screen.getOrientation() === 'land'
? this.config.landColumns
: this.config.portColumns;
}
Затем сетка измеряет карточки, вычисляет общий размер и вписывает результат в доступную область:
const fitScale = ScreenFitLayoutResolver.resolveScale({
contentWidth: gridWidth <= 0 ? 1 : gridWidth,
contentHeight: gridHeight <= 0 ? 1 : gridHeight,
availableWidth,
availableHeight,
minScale: 0,
maxScale: this.config.maxScale,
});
Это практический шаблон:
- Выбрать структуру UX для текущей ориентации.
- Измерить фактическое содержимое.
- Вписать результат в экран.