Связка Mapbox GL JS и Deck.gl формирует архитектуру, в которой Mapbox отвечает за рендеринг базовой карты и управление камерой, а Deck.gl — за высокоуровневую визуализацию больших наборов данных поверх карты. Такая модель позволяет разделить ответственность: карта остаётся интерактивной и быстрой, а сложные визуальные слои выполняются WebGL-движком Deck.gl.
Основная идея заключается в использовании Deck.gl как оверлея, синхронизированного с состоянием камеры Mapbox GL JS. При каждом изменении viewport данные пересчитываются и перерисовываются в соответствии с текущим состоянием карты.
Deck.gl не заменяет Mapbox GL JS, а встраивается в его рендеринг как дополнительный слой. В зависимости от версии API используются два основных подхода:
MapboxOverlay (современный способ интеграции)CustomLayerInterface (низкоуровневый метод
Mapbox)В обоих случаях Deck.gl получает матрицы камеры и параметры вида от Mapbox, после чего строит собственную сцену WebGL.
Ключевые элементы архитектуры:
Deck.gl работает с концепцией слоёв (layers), каждый из которых описывает, как визуализировать набор данных. Каждый слой является иммутабельной декларацией:
data)Типовые слои:
ScatterplotLayer — точкиGeoJsonLayer — геометрии GeoJSONLineLayer — линии маршрутовPolygonLayer — полигоныArcLayer — дуги между точкамиКаждый слой оптимизирован под GPU и использует WebGL для батчинга отрисовки.
Современный способ интеграции основан на объекте
MapboxOverlay, который связывает экземпляр Deck.gl с Mapbox
GL JS.
import mapboxgl from 'mapbox-gl';
import { MapboxOverlay } from '@deck.gl/mapbox';
import { ScatterplotLayer } from '@deck.gl/layers';
mapboxgl.accessToken = 'YOUR_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v11',
center: [37.618423, 55.751244],
zoom: 10
});
const deckOverlay = new MapboxOverlay({
layers: [
new ScatterplotLayer({
id: 'scatter',
data: [
{ position: [37.62, 55.75], size: 100 }
],
getPosition: d => d.position,
getRadius: d => d.size,
getFillColor: [255, 140, 0]
})
]
});
map.addControl(deckOverlay);
В этом режиме Deck.gl полностью синхронизируется с картой, включая:
Низкоуровневая интеграция через Mapbox Custom Layer Interface позволяет вручную управлять жизненным циклом WebGL-контекста.
const deckLayer = {
id: 'custom-deck',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
this.deck = new Deck({
gl,
layers: [
new ScatterplotLayer({
data: [],
getPosition: d => d.position,
getRadius: 50
})
]
});
},
render: function (gl, matrix) {
this.deck.setProps({
viewState: {
longitude: map.getCenter().lng,
latitude: map.getCenter().lat,
zoom: map.getZoom(),
bearing: map.getBearing(),
pitch: map.getPitch()
}
});
this.deck.redraw();
}
};
map.on('load', () => {
map.addLayer(deckLayer);
});
Этот подход требует ручного управления синхронизацией, но даёт полный контроль над пайплайном рендеринга.
Mapbox GL JS использует Web Mercator projection, и Deck.gl работает в той же системе координат, что обеспечивает прямую совместимость.
Основные параметры синхронизации:
longitudelatitudezoombearingpitchDeck.gl преобразует географические координаты в экранные через матрицы:
При каждом движении карты пересчитываются трансформации, что обеспечивает плавную интерактивность.
Deck.gl рассчитан на обработку больших массивов данных (сотни тысяч и миллионы объектов). Основные механизмы оптимизации:
WebGL instancing позволяет рендерить множество объектов одним draw call.
Некоторые слои используют spatial indexing для отсечения невидимых объектов.
Данные передаются в GPU через буферы, минимизируя JavaScript-вычисления во время рендера.
Перерисовка происходит только при изменении props слоя.
GeoJsonLayer является одним из самых гибких инструментов для визуализации пространственных данных.
import { GeoJsonLayer } from '@deck.gl/layers';
const layer = new GeoJsonLayer({
id: 'geojson',
data: 'https://example.com/data.geojson',
stroked: true,
filled: true,
getFillColor: [0, 128, 255],
getLineColor: [255, 255, 255],
lineWidthMinPixels: 2
});
Особенности:
Deck.gl предоставляет event system для обработки пользовательских взаимодействий:
onClickonHoveronDragПример обработки:
new ScatterplotLayer({
data,
pickable: true,
onClick: info => {
const object = info.object;
console.log(object);
}
});
Hit-testing выполняется на GPU, что позволяет быстро определять объекты под курсором.
Deck.gl поддерживает полноценные 3D-слои, включая высотные экструдированные полигоны и геометрии.
new PolygonLayer({
data,
extruded: true,
getElevation: d => d.height,
getFillColor: [200, 0, 80]
});
При включённом pitch Mapbox GL JS сцена становится трёхмерной, а Deck.gl синхронно отрисовывает объекты в том же пространстве.
Deck.gl использует immutable-подход: любые изменения данных или стиля создают новую версию слоя.
Основные параметры обновления:
data пересоздаёт буферыget*) требует пересчёта
атрибутовТакой подход снижает количество побочных эффектов и упрощает прогнозирование рендера.
Deck.gl оверлей не конфликтует с нативными слоями Mapbox GL JS. Порядок рендеринга контролируется:
beforeId (в Mapbox)Типичная схема:
При увеличении объёма данных используются стратегии:
Deck.gl может работать как с raw data, так и с tile-based источниками.
Для повышения производительности поддерживаются бинарные форматы:
Это снижает нагрузку на парсинг и уменьшает время передачи данных в GPU.
Mapbox GL JS передаёт события движения камеры:
movezoomrotatepitchDeck.gl подписывается на эти события через overlay и пересчитывает viewState. Это обеспечивает синхронность между картой и визуализацией без ручного обновления состояния.
Deck.gl может использовать:
При интеграции через overlay используется общий контекст, что снижает накладные расходы и исключает дублирование ресурсов GPU.
Ресурсы управляются через:
onAdd, onRemove)getPosition,
getColor)При работе с большими данными используется комбинация:
Такая архитектура позволяет визуализировать данные в реальном времени без деградации FPS даже при высокой плотности объектов