В основе системы визуализации Deck.gl лежит разделение сцены на независимые представления (Views), каждое из которых описывает собственную камеру, систему координат, параметры проекции и область рендеринга на канвасе. Эта архитектура позволяет строить сложные композиции визуализаций: от классических карт с дополнительными вставками до мультиоконных аналитических панелей и синхронизированных 3D-сцен.
Множественные представления формируют слой абстракции между данными и их визуальным отображением, отделяя:
Каждое представление в Deck.gl — это самостоятельная единица рендеринга, которая может использовать общий набор слоёв или собственную подмножество слоёв.
Внутренне Deck.gl оперирует двумя ключевыми сущностями:
View — декларативное описание камеры и области отображения.
Viewport — вычисленный объект, содержащий матрицы проекции и преобразования координат для конкретного кадра.
View задаёт параметры высокого уровня:
Viewport — результат вычислений, используемый на этапе рендеринга WebGL.
Ключевой момент архитектуры: View не участвует в рендеринге напрямую, он трансформируется в Viewport через состояние приложения и взаимодействие пользователя.
Deck.gl предоставляет несколько стандартных реализаций View, каждая из которых оптимизирована под определённый сценарий.
Ориентирован на геопространственные данные и работает в связке с проекциями карт.
Особенности:
MapView используется как базовый элемент для большинства гео-визуализаций.
Предназначен для 3D-сцен с орбитальной камерой.
Характеристики:
OrbitView часто применяется в инженерной визуализации и научных данных.
Модель камеры от первого лица:
Используется для 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: []
});
В этом примере сцена разделена на две области:
Каждое представление имеет собственные координаты и независимое управление.
Один из ключевых механизмов Deck.gl — возможность привязывать слои к конкретным View.
Каждый слой может быть:
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
}
}
});
}
Синхронизация используется для:
Каждый View в процессе рендеринга преобразуется в Viewport, который содержит:
Deck.gl автоматически распределяет canvas на области, соответствующие конфигурации views.
Пример разделения:
Каждый фрагмент сцены получает собственный WebGL viewport.
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
}
});
}
Эта модель позволяет масштабировать количество представлений без изменения архитектуры приложения.
Множественные представления часто используются для построения сложных интерфейсов:
Каждое представление может иметь собственный 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, поскольку:
Оптимизационные подходы:
viewIds для фильтрации слоёв;controller: false) для
статичных представлений;binary data форматы;В некоторых приложениях View создаются и уничтожаются динамически:
this.setState({
views: showGlobe
? [new MapView(), new OrbitView()]
: [new MapView()]
});
Это позволяет строить адаптивные интерфейсы, где количество представлений зависит от режима работы приложения.
При наличии нескольких View события взаимодействия должны корректно маршрутизироваться:
onClick: info => {
const {viewId, object} = info;
console.log(viewId, object);
}
Это критично для интерфейсов сравнения и аналитики, где одинаковые объекты могут присутствовать в разных представлениях.
Каждое View работает в собственной системе координат:
Deck.gl автоматически преобразует координаты данных в пространство каждого View через pipeline трансформаций.
Это позволяет использовать один и тот же набор данных в совершенно разных визуальных контекстах без дополнительной подготовки.