← На главную
Серия практических разборов

Композиция сцены и сетка каталога

Адаптивная вёрстка HTML5-игры для Poki • Раздел 5 из 11

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,
});

Это практический шаблон:

  1. Выбрать структуру UX для текущей ориентации.
  2. Измерить фактическое содержимое.
  3. Вписать результат в экран.