Множественные представления

В основе системы визуализации Deck.gl лежит разделение сцены на независимые представления (Views), каждое из которых описывает собственную камеру, систему координат, параметры проекции и область рендеринга на канвасе. Эта архитектура позволяет строить сложные композиции визуализаций: от классических карт с дополнительными вставками до мультиоконных аналитических панелей и синхронизированных 3D-сцен.

Множественные представления формируют слой абстракции между данными и их визуальным отображением, отделяя:

  • геометрию и слои данных;
  • параметры камеры;
  • область вывода (viewport bounds);
  • интерактивное поведение.

Каждое представление в Deck.gl — это самостоятельная единица рендеринга, которая может использовать общий набор слоёв или собственную подмножество слоёв.


Базовая модель View и Viewport

Внутренне Deck.gl оперирует двумя ключевыми сущностями:

View — декларативное описание камеры и области отображения.

Viewport — вычисленный объект, содержащий матрицы проекции и преобразования координат для конкретного кадра.

View задаёт параметры высокого уровня:

  • тип камеры (карта, орбита, first-person);
  • положение и масштаб;
  • размеры области на canvas;
  • ограничения взаимодействия.

Viewport — результат вычислений, используемый на этапе рендеринга WebGL.

Ключевой момент архитектуры: View не участвует в рендеринге напрямую, он трансформируется в Viewport через состояние приложения и взаимодействие пользователя.


Типы представлений

Deck.gl предоставляет несколько стандартных реализаций View, каждая из которых оптимизирована под определённый сценарий.

MapView

Ориентирован на геопространственные данные и работает в связке с проекциями карт.

Особенности:

  • поддержка широты и долготы;
  • интеграция с tile-based системами;
  • соответствие стандартным картографическим проекциям;
  • синхронизация с библиотеками вроде Mapbox.

MapView используется как базовый элемент для большинства гео-визуализаций.


OrbitView

Предназначен для 3D-сцен с орбитальной камерой.

Характеристики:

  • вращение вокруг центра сцены;
  • управление через pitch/yaw/zoom;
  • фиксированная точка фокуса;
  • удобен для анализа 3D-объектов и структур.

OrbitView часто применяется в инженерной визуализации и научных данных.


FirstPersonView

Модель камеры от первого лица:

  • перемещение по сцене как в игровом движке;
  • управление направлением взгляда;
  • поддержка WASD-навигации (через контроллеры);
  • полезен для симуляций и навигации в пространственных данных.

OrthographicView

Используется для 2D-визуализаций без перспективного искажения:

  • параллельная проекция;
  • точное измерение расстояний;
  • аналитические интерфейсы и схемы.

Конфигурация множественных представлений

Deck.gl позволяет одновременно использовать несколько Views внутри одного экземпляра Deck. Это задаётся через массив views.

import {Deck} from '@deck.gl/core';
import {MapView, OrbitView} from '@deck.gl/core';

const deckgl = new Deck({
  views: [
    new MapView({
      id: 'map',
      controller: true,
      width: '70%',
      height: '100%'
    }),
    new OrbitView({
      id: 'globe',
      controller: true,
      x: '70%',
      width: '30%',
      height: '100%'
    })
  ],
  initialViewState: {
    map: {
      longitude: 30,
      latitude: 50,
      zoom: 4
    },
    globe: {
      target: [0, 0, 0],
      zoom: 1
    }
  },
  layers: []
});

В этом примере сцена разделена на две области:

  • основная карта (70% ширины);
  • 3D-объект (30% ширины).

Каждое представление имеет собственные координаты и независимое управление.


Привязка слоёв к представлениям

Один из ключевых механизмов Deck.gl — возможность привязывать слои к конкретным View.

Каждый слой может быть:

  • глобальным (рендерится во всех View);
  • ограниченным по id представления.
import {ScatterplotLayer} from '@deck.gl/layers';

const layer = new ScatterplotLayer({
  id: 'points',
  data: points,
  getPosition: d => d.coordinates,
  getRadius: 1000,
  getFillColor: [255, 0, 0],
  visible: true,
  parameters: {
    depthTest: false
  }
});

Привязка к view:

layer.props.visible = true;
layer.props.getPolygonOffset = () => [0, -1000];

layer.props = {
  ...layer.props,
  visible: true,
  pickable: true
};

В более сложных сценариях используется фильтрация через viewId:

new ScatterplotLayer({
  id: 'points-map',
  data,
  getPosition: d => d.pos,
  visible: true,
  viewIds: ['map']
});

Синхронизация представлений

Множественные View могут быть:

Независимыми

Каждое представление управляет собственным состоянием камеры.

  • разные центры;
  • разные данные;
  • отсутствие связи между камерами.

Используется для сравнительного анализа.


Синхронизированными

Один ViewState может контролировать несколько представлений.

onViewStateChange: ({viewId, viewState}) => {
  this.setState({
    viewState: {
      map: viewState,
      globe: {
        ...viewState,
        rotationX: viewState.rotationX * 0.5
      }
    }
  });
}

Синхронизация используется для:

  • мини-карт;
  • 2D/3D связки;
  • сравнительных режимов;
  • дублирования камеры.

Множественные Viewport и расчёт области рендеринга

Каждый View в процессе рендеринга преобразуется в Viewport, который содержит:

  • матрицу вида (view matrix);
  • матрицу проекции;
  • размеры viewport;
  • координатные преобразования.

Deck.gl автоматически распределяет canvas на области, соответствующие конфигурации views.

Пример разделения:

  • x: 0–500px → MapView;
  • x: 500–800px → OrbitView.

Каждый фрагмент сцены получает собственный WebGL viewport.


Общий ViewState и управление состоянием

ViewState — централизованная структура, описывающая параметры всех камер.

initialViewState: {
  map: {
    longitude: 10,
    latitude: 50,
    zoom: 5,
    bearing: 0,
    pitch: 0
  },
  orbit: {
    target: [0, 0, 0],
    zoom: 1
  }
}

Обновление состояния происходит через:

onViewStateChange: ({viewId, viewState}) => {
  this.setState({
    viewState: {
      ...this.state.viewState,
      [viewId]: viewState
    }
  });
}

Эта модель позволяет масштабировать количество представлений без изменения архитектуры приложения.


Вложенные и композиционные сценарии

Множественные представления часто используются для построения сложных интерфейсов:

Мини-карта

  • основной MapView;
  • дополнительный уменьшенный MapView;
  • синхронизация центра и масштаба.

Аналитическая панель

  • один View отображает 2D граф;
  • второй View — географическую проекцию;
  • третий View — 3D модель.

Split-screen сравнение

  • одинаковые данные;
  • разные стили слоёв;
  • независимые камеры.

Управление взаимодействием

Каждое представление может иметь собственный controller:

new MapView({
  controller: {
    dragRotate: false,
    scrollZoom: true
  }
})

Контроллеры управляют:

  • зумом;
  • панорамированием;
  • вращением;
  • ограничениями движения.

В мульти-view конфигурациях важно разделять управление, чтобы избежать конфликтов событий мыши и touch.


Переиспользование слоёв между представлениями

Deck.gl позволяет использовать один набор слоёв сразу в нескольких View, что снижает нагрузку и упрощает архитектуру.

const layers = [
  new ScatterplotLayer({
    id: 'shared-points',
    data,
    getPosition: d => d.position
  })
];

Эти слои автоматически рендерятся в каждом View, если не задано ограничение viewIds.


Производительность при множественных представлениях

Использование нескольких View увеличивает нагрузку на WebGL pipeline, поскольку:

  • каждый View требует отдельной матрицы проекции;
  • увеличивается количество draw calls;
  • возрастает нагрузка на фрагментный шейдер при пересечении слоёв.

Оптимизационные подходы:

  • ограничение количества активных View;
  • использование viewIds для фильтрации слоёв;
  • отключение взаимодействия (controller: false) для статичных представлений;
  • кеширование геометрии через binary data форматы;
  • минимизация пересчёта viewState.

Динамическое переключение представлений

В некоторых приложениях View создаются и уничтожаются динамически:

this.setState({
  views: showGlobe
    ? [new MapView(), new OrbitView()]
    : [new MapView()]
});

Это позволяет строить адаптивные интерфейсы, где количество представлений зависит от режима работы приложения.


Событийная модель в мульти-view сценах

При наличии нескольких View события взаимодействия должны корректно маршрутизироваться:

  • pointer events привязываются к конкретному viewport;
  • pick events содержат информацию о viewId;
  • hover и click обрабатываются с учётом z-index View.
onClick: info => {
  const {viewId, object} = info;
  console.log(viewId, object);
}

Это критично для интерфейсов сравнения и аналитики, где одинаковые объекты могут присутствовать в разных представлениях.


Геометрическая независимость представлений

Каждое View работает в собственной системе координат:

  • MapView использует географические координаты;
  • OrbitView — декартову систему;
  • OrthographicView — нормализованную 2D-плоскость.

Deck.gl автоматически преобразует координаты данных в пространство каждого View через pipeline трансформаций.

Это позволяет использовать один и тот же набор данных в совершенно разных визуальных контекстах без дополнительной подготовки.