MapView

deck.gl предоставляет абстракции для высокопроизводительного рендеринга геоданных поверх WebGL-контекста, а компонент представления отвечает за организацию камеры, проекции и взаимодействия с пользователем. Одним из базовых элементов этой системы является MapView, который определяет геометрическое пространство отображения и управляет тем, как сцена со слоями интерпретируется в координатах карты.

MapView представляет собой описание “вида” (view), включающее систему координат, параметры камеры и поведенческие настройки взаимодействия. Он не занимается отрисовкой слоёв напрямую, а формирует контекст, в котором слои рендерятся. В типичной архитектуре deck.gl MapView используется совместно с контейнером Deck, который агрегирует несколько представлений и слоёв, распределяя их по разным областям экрана или разным камерам.

MapView опирается на концепцию географического пространства, где данные интерпретируются в координатах долготы и широты. Основная задача — преобразование этих координат в экранное пространство с учётом уровня масштабирования, центра карты и проекции.

Ключевые параметры:

  • longitude / latitude — центр сцены в географических координатах
  • zoom — уровень масштабирования
  • bearing — угол поворота карты относительно севера
  • pitch — наклон камеры относительно плоскости карты

Эти параметры формируют объект viewState, который является единственным источником истины для позиции камеры в MapView.

Создание MapView и базовая структура

MapView задаётся как объект конфигурации и передаётся в контейнер рендера.

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

const view = new MapView({
  id: 'map-view',
  controller: true
});

const deckgl = new Deck({
  views: [view],
  initialViewState: {
    longitude: 37.6173,
    latitude: 55.7558,
    zoom: 10,
    pitch: 0,
    bearing: 0
  },
  layers: []
});

В этом контексте MapView задаёт поведение сцены, а Deck управляет жизненным циклом рендеринга.

Связь MapView и viewState

Состояние камеры отделено от представления и хранится в viewState. MapView интерпретирует это состояние и применяет его к матрицам преобразования.

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

  • MapView не хранит внутреннего состояния камеры
  • Любое изменение происходит через обновление viewState
  • Переходы между состояниями могут анимироваться внешними средствами deck.gl

Пример изменения состояния:

deckgl.setProps({
  viewState: {
    longitude: 30.31,
    latitude: 59.93,
    zoom: 12,
    pitch: 45,
    bearing: 20
  }
});

MapView автоматически пересчитывает матрицы проекции и трансформации при обновлении состояния.

Взаимодействие с контроллерами

MapView поддерживает подключение интерактивных контроллеров, которые обрабатывают пользовательский ввод и изменяют viewState.

const view = new MapView({
  id: 'interactive-map',
  controller: {
    dragPan: true,
    scrollZoom: true,
    doubleClickZoom: true,
    touchRotate: true
  }
});

Контроллер в MapView реализует стандартные взаимодействия:

  • перетаскивание изменяет longitude/latitude
  • прокрутка изменяет zoom
  • жесты вращения изменяют bearing
  • наклон изменяет pitch

При этом MapView не интерпретирует события напрямую, а преобразует их в изменения состояния камеры.

Проекционная модель

MapView использует Web Mercator как базовую проекцию по умолчанию. Это обеспечивает совместимость с большинством тайловых карт и GIS-систем.

Характерные свойства:

  • меркаторская проекция искажает площади на высоких широтах
  • прямые линии на экране не всегда соответствуют геодезическим линиям
  • масштабирование экспоненциально зависит от zoom

Преобразование координат происходит в несколько этапов:

  1. Географические координаты (lon/lat)
  2. Проекция в метры Web Mercator
  3. Нормализация под текущий zoom
  4. Преобразование в экранные координаты

Использование с слоями

MapView не содержит логики слоёв, но определяет контекст их отрисовки. Слои, такие как ScatterplotLayer, ArcLayer или PolygonLayer, получают трансформированные координаты через контекст view.

Пример:

import {ScatterplotLayer} from '@deck.gl/layers';

const layer = new ScatterplotLayer({
  id: 'points',
  data: [{position: [37.62, 55.75]}],
  getPosition: d => d.position,
  getRadius: 1000,
  getFillColor: [255, 0, 0]
});

MapView обеспечивает правильную интерпретацию этих координат в рамках текущего viewState.

Мультивью и композиция сцен

MapView может использоваться совместно с другими представлениями, формируя многослойные интерфейсы.

Типовые сценарии:

  • один MapView для основной карты
  • дополнительный View для миникарты
  • синхронизация нескольких камер

Пример конфигурации:

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

const mainView = new MapView({
  id: 'main'
});

const secondaryView = new MapView({
  id: 'secondary',
  x: 0,
  y: 0,
  width: '30%',
  height: '30%'
});

new Deck({
  views: [mainView, secondaryView],
  viewState: {
    main: {
      longitude: 10,
      latitude: 50,
      zoom: 5
    },
    secondary: {
      longitude: 20,
      latitude: 55,
      zoom: 3
    }
  },
  layers: []
});

Каждый MapView получает собственное состояние камеры и собственную область рендеринга.

Координатные трансформации и матрицы

Внутри MapView используется цепочка матриц:

  • view matrix (камера)
  • projection matrix (проекция)
  • view-projection matrix (комбинация)

Эти матрицы применяются к атрибутам вершин в WebGL шейдерах. MapView формирует параметры, которые передаются в слой, где происходит финальная трансформация.

Особое значение имеет инверсия матрицы для вычисления географических координат из экранных:

  • screen → world
  • world → geographic

Это позволяет реализовать интерактивные операции: выбор объектов, hit-testing, выделение областей.

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

MapView проектируется с учётом больших объёмов данных. Основные оптимизации:

  • минимизация пересчёта матриц при неизменном viewState
  • использование GPU для трансформаций
  • батчинг рендеринга слоёв
  • кэширование проекций

Критическим фактором является стабильность viewState: частые мелкие обновления камеры могут приводить к перерасчёту большого количества данных.

Ограничения и особенности поведения

MapView предполагает плоскую карту в Web Mercator пространстве, что накладывает ограничения:

  • невозможность корректного отображения полярных областей без искажений
  • ограниченная точность при экстремальных zoom-уровнях
  • зависимость от WebGL контекста

При этом модель остаётся универсальной для большинства картографических приложений, ориентированных на интерактивную визуализацию данных.

Интеграция с внешними картографическими слоями

MapView может работать поверх тайловых слоёв из внешних источников, включая Mapbox или собственные tile servers. В таких случаях синхронизация viewState становится критическим элементом архитектуры.

Типичная схема:

  • MapView управляет камерой
  • тайловый слой получает bounding box
  • слой данных синхронизируется с zoom и center

Это обеспечивает согласованное отображение географических данных и визуальных элементов сцены.