Архитектура приложения на Deck.gl строится вокруг нескольких ключевых сущностей: контейнера рендеринга, WebGL-контекста, слоя (Layer) и источника данных. Даже минимальная конфигурация предполагает наличие связки между картографической подложкой и визуализационным слоем, который отвечает за отрисовку геометрии.
Deck.gl может использоваться как самостоятельный WebGL-рендерер или в
связке с картографическими библиотеками (Mapbox GL JS, Google Maps). В
минимальном варианте без карты достаточно создать контейнер и экземпляр
Deck.
Основные зависимости:
@deck.gl/core@deck.gl/layersПростейшая структура подключения:
import {Deck} from '@deck.gl/core';
import {ScatterplotLayer} from '@deck.gl/layers';
Контейнер для рендеринга задаётся через DOM-элемент:
<div id="deck-container" style="width: 100vw; height: 100vh;"></div>
Центральная точка приложения — объект Deck. Он управляет
WebGL-контекстом, жизненным циклом слоёв и обновлениями состояния.
const deckgl = new Deck({
container: 'deck-container',
initialViewState: {
longitude: 37.6173,
latitude: 55.7558,
zoom: 10,
pitch: 0,
bearing: 0
},
controller: true,
layers: []
});
Deck.gl не оперирует «сценой» в классическом смысле. Вместо этого используется декларативная модель слоёв.
Каждый слой описывает:
Пример базового слоя:
const layer = new ScatterplotLayer({
id: 'scatter-layer',
data: [
{position: [37.6173, 55.7558], size: 1000}
],
getPosition: d => d.position,
getRadius: d => d.size,
getFillColor: [255, 0, 0]
});
Deck.gl использует реактивный подход: изменение массива слоёв приводит к перерасчёту сцены.
deckgl.setProps({
layers: [layer]
});
Либо слои задаются сразу при инициализации:
const deckgl = new Deck({
container: 'deck-container',
initialViewState: {
longitude: 37.6173,
latitude: 55.7558,
zoom: 10
},
controller: true,
layers: [
new ScatterplotLayer({
id: 'points',
data: [
{position: [37.6173, 55.7558], size: 500}
],
getPosition: d => d.position,
getRadius: d => d.size,
getFillColor: [0, 128, 255]
})
]
});
Ключевой принцип Deck.gl — разделение данных и их визуального представления.
Слой не изменяет данные, а описывает, как их интерпретировать:
data — массив или поток данныхaccessor-функции — извлечение значенийПример с вычисляемыми свойствами:
getFillColor: d => d.value > 10 ? [255, 0, 0] : [0, 255, 0]
Deck.gl не требует ручного перерисовывания сцены. Любое изменение конфигурации слоя или данных приводит к автоматическому обновлению.
Типичный цикл обновления:
const updatedLayer = new ScatterplotLayer({
...layer.props,
data: newData
});
deckgl.setProps({
layers: [updatedLayer]
});
Важный аспект: новый слой рассматривается как независимая сущность,
даже при сохранении id.
Параметр initialViewState задаёт начальную позицию, но
дальнейшее управление осуществляется через обновление состояния.
deckgl.setProps({
viewState: {
longitude: 30.3351,
latitude: 59.9343,
zoom: 12,
pitch: 45,
bearing: 30
}
});
Камера в Deck.gl является частью реактивной модели и может быть синхронизирована с внешними источниками состояния.
Типовая структура приложения без фреймворков:
/project
index.html
index.js
package.json
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Deck.gl App</title>
<style>
body { margin: 0; }
#deck-container { width: 100vw; height: 100vh; }
</style>
</head>
<body>
<div id="deck-container"></div>
<script src="./dist/bundle.js"></script>
</body>
</html>
import {Deck} from '@deck.gl/core';
import {ScatterplotLayer} from '@deck.gl/layers';
const data = [
{position: [37.6173, 55.7558], value: 1},
{position: [30.3351, 59.9343], value: 20}
];
new Deck({
container: 'deck-container',
initialViewState: {
longitude: 37.6173,
latitude: 55.7558,
zoom: 4
},
controller: true,
layers: [
new ScatterplotLayer({
id: 'points',
data,
getPosition: d => d.position,
getRadius: d => d.value * 1000,
getFillColor: d => d.value > 10 ? [255, 80, 80] : [80, 160, 255]
})
]
});
Deck.gl использует WebGL как низкоуровневый слой отрисовки. При каждом обновлении:
Эта архитектура минимизирует количество draw-call’ов и обеспечивает высокую производительность даже при больших объёмах данных.
Поле id используется для:
new ScatterplotLayer({
id: 'stable-layer',
...
});
Изменение id фактически создаёт новый слой без
наследования оптимизаций предыдущего.
Deck.gl допускает различные формы источников данных:
Пример GeoJSON:
import {GeoJsonLayer} from '@deck.gl/layers';
new GeoJsonLayer({
id: 'geojson',
data: 'https://example.com/data.geojson',
filled: true,
getFillColor: [200, 0, 80]
});
Даже без использования React или других фреймворков Deck.gl поддерживает реактивность через:
setPropsviewStateЭто формирует однонаправленный поток данных:
данные → слой → WebGL → изображение
При работе без дополнительных библиотек отсутствуют:
Поэтому координаты интерпретируются напрямую в системе долгот и широт без преобразований со стороны карты.
DOM-элемент выполняет исключительно функцию поверхности для WebGL-контекста. Все вычисления происходят вне DOM-дерева.
container: document.getElementById('deck-container')
Любые стили контейнера влияют только на размер canvas, но не на геометрию сцены.
Оптимизированный подход предполагает сохранение экземпляра слоя:
const layer = new ScatterplotLayer({
id: 'points',
data: initialData
});
function update(newData) {
deckgl.setProps({
layers: [
layer.clone({data: newData})
]
});
}
Метод clone сохраняет внутренние оптимизации WebGL и
снижает нагрузку на пересборку буферов.
Deck
├── ViewState (камера)
├── Layers[]
│ ├── Data
│ ├── Accessors
│ └── Render state
└── WebGLRenderer
Эта структура остаётся неизменной независимо от сложности приложения.