Deck.gl представляет собой высокопроизводительную библиотеку визуализации пространственных данных, построенную поверх WebGL. Несмотря на широкую популярность интеграции с React, библиотека изначально проектировалась как независимый графический движок и может полноценно использоваться в обычных проектах на vanilla JavaScript без применения фреймворков.
Подход без React особенно востребован в следующих сценариях:
Основным объектом управления становится экземпляр класса
Deck, который отвечает за создание WebGL-контекста,
управление слоями, обработку событий и обновление сцены.
Наиболее простой вариант — использование CDN.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Deck.gl</title>
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<style>
body {
margin: 0;
}
#container {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
После подключения становится доступно глобальное пространство имён:
deck
Например:
const deckInstance = new deck.Deck({
parent: document.getElementById('container')
});
Минимальная конфигурация включает контейнер и начальное состояние камеры.
const deckgl = new deck.Deck({
parent: document.getElementById('container'),
initialViewState: {
longitude: 37.6176,
latitude: 55.7558,
zoom: 10,
pitch: 0,
bearing: 0
},
controller: true
});
| Параметр | Назначение |
|---|---|
| parent | DOM-контейнер |
| layers | массив слоёв |
| initialViewState | начальная камера |
| controller | управление мышью |
| views | настройка представлений |
| effects | графические эффекты |
| onClick | обработчик клика |
| onHover | обработчик наведения |
Вся визуализация в Deck.gl строится вокруг концепции слоёв (Layers).
Каждый слой представляет определённый способ отображения данных:
Слои передаются через параметр layers.
deckgl.setProps({
layers: [
layer1,
layer2,
layer3
]
});
Один из самых популярных слоёв — отображение точек.
const points = [
{
position: [37.62, 55.75],
size: 100,
color: [255, 0, 0]
},
{
position: [37.70, 55.80],
size: 200,
color: [0, 0, 255]
}
];
const scatterLayer = new deck.ScatterplotLayer({
id: 'scatter',
data: points,
getPosition: d => d.position,
getRadius: d => d.size,
getFillColor: d => d.color,
radiusMinPixels: 5,
pickable: true
});
Добавление слоя:
deckgl.setProps({
layers: [scatterLayer]
});
Размер может задаваться несколькими способами.
getRadius: 50
getRadius: d => d.population
radiusMinPixels: 2,
radiusMaxPixels: 100
Deck.gl использует формат RGBA.
[255, 0, 0]
Красный цвет.
[0, 255, 0]
Зелёный цвет.
[0, 0, 255]
Синий цвет.
[255, 0, 0, 120]
Полупрозрачный красный.
Динамическое вычисление цвета:
getFillColor: d => {
if (d.value > 1000) {
return [255, 0, 0];
}
return [0, 255, 0];
}
const scatterLayer = new deck.ScatterplotLayer({
id: 'scatter',
data,
pickable: true,
onHover: info => {
console.log(info);
}
});
Объект info содержит:
{
object,
x,
y,
coordinate,
index,
layer
}
const scatterLayer = new deck.ScatterplotLayer({
id: 'scatter',
data,
pickable: true,
onClick: info => {
console.log(info.object);
}
});
Deck.gl не предоставляет встроенный компонент tooltip, однако позволяет создавать его через DOM.
const tooltip = document.createElement('div');
tooltip.style.position = 'absolute';
tooltip.style.display = 'none';
document.body.appendChild(tooltip);
Использование:
onHover: info => {
if (!info.object) {
tooltip.style.display = 'none';
return;
}
tooltip.style.display = 'block';
tooltip.style.left = `${info.x}px`;
tooltip.style.top = `${info.y}px`;
tooltip.textContent = info.object.name;
}
Слой предназначен для отображения связей между двумя точками.
const routes = [
{
source: [37.62, 55.75],
target: [30.31, 59.93]
}
];
const arcLayer = new deck.ArcLayer({
id: 'arc',
data: routes,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: [0, 128, 255],
getTargetColor: [255, 0, 0],
getWidth: 5
});
Предназначен для отображения прямых линий.
const lineLayer = new deck.LineLayer({
id: 'line',
data: routes,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getColor: [255, 140, 0],
getWidth: 4
});
Используется для отображения областей и геометрий.
const polygons = [
{
contour: [
[37.60, 55.70],
[37.70, 55.70],
[37.70, 55.80],
[37.60, 55.80]
]
}
];
const polygonLayer = new deck.PolygonLayer({
id: 'polygon',
data: polygons,
getPolygon: d => d.contour,
getFillColor: [0, 128, 255, 120],
getLineColor: [0, 0, 0],
getLineWidth: 2,
stroked: true,
filled: true
});
Один из наиболее мощных слоёв библиотеки.
Позволяет визуализировать GeoJSON без дополнительной обработки.
const geojson = {
type: "FeatureCollection",
features: [...]
};
const geoJsonLayer = new deck.GeoJsonLayer({
id: 'geojson',
data: geojson,
filled: true,
stroked: true,
pickable: true,
getFillColor: [0, 150, 255, 100],
getLineColor: [0, 0, 0]
});
Часто данные поступают из API.
async function loadData() {
const response = await fetch('/api/points');
const data = await response.json();
const layer = new deck.ScatterplotLayer({
id: 'points',
data,
getPosition: d => d.coordinates
});
deckgl.setProps({
layers: [layer]
});
}
loadData();
Deck.gl эффективно обновляет сцену при изменении свойств.
function updateData(newData) {
const layer = new deck.ScatterplotLayer({
id: 'points',
data: newData,
getPosition: d => d.position
});
deckgl.setProps({
layers: [layer]
});
}
Повторное создание слоя считается стандартной практикой в Deck.gl.
Обычно сцена состоит из нескольких визуализаций одновременно.
deckgl.setProps({
layers: [
polygonLayer,
lineLayer,
scatterLayer
]
});
Порядок имеет значение.
Слои отображаются сверху вниз:
layers: [
backgroundLayer,
roadsLayer,
markersLayer
]
Последний слой располагается поверх предыдущих.
Текущее состояние камеры можно менять программно.
deckgl.setProps({
viewState: {
longitude: 37.6176,
latitude: 55.7558,
zoom: 12,
pitch: 45,
bearing: 30
}
});
deckgl.setProps({
viewState: {
longitude: 37.6176,
latitude: 55.7558,
zoom: 12,
transitionDuration: 3000
}
});
По умолчанию Deck.gl работает через картографическое представление.
const view = new deck.MapView({
repeat: true
});
Подключение:
const deckgl = new deck.Deck({
views: [view]
});
Deck.gl часто используется поверх картографической подложки.
<link
href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css"
rel="stylesheet">
<script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
Создание карты:
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [37.6176, 55.7558],
zoom: 10
});
Создание Deck.gl поверх карты:
const deckOverlay = new deck.MapboxOverlay({
layers: [scatterLayer]
});
map.addControl(deckOverlay);
Такой подход обеспечивает синхронизацию карты и WebGL-визуализации.
Для отображения подписей применяется TextLayer.
const textLayer = new deck.TextLayer({
id: 'labels',
data,
getPosition: d => d.position,
getText: d => d.name,
getSize: 18,
getColor: [0, 0, 0]
});
Слой позволяет отображать пользовательские иконки.
const iconLayer = new deck.IconLayer({
id: 'icons',
data,
pickable: true,
iconAtlas: './icons.png',
iconMapping: './icons.json',
getIcon: d => 'marker',
getPosition: d => d.position,
getSize: 32
});
Предназначен для отображения плотности данных.
const heatmapLayer = new deck.HeatmapLayer({
id: 'heatmap',
data,
getPosition: d => d.position,
getWeight: d => d.value
});
Тепловые карты особенно эффективны при работе с десятками тысяч точек.
Deck.gl создавался для обработки миллионов объектов.
Основные рекомендации:
Вместо сложных объектов:
[
{
lat: 55.7,
lng: 37.6
}
]
предпочтительно использовать:
Float32Array
или
Float64Array
Менее эффективно:
getRadius: d => expensiveCalculation(d)
Более эффективно:
data.forEach(item => {
item.radius = expensiveCalculation(item);
});
getRadius: d => d.radius
Плохо:
setInterval(() => {
deckgl.setProps({
layers: createLayers()
});
}, 50);
Лучше:
updateOnlyWhenDataChanged();
При удалении визуализации необходимо освобождать ресурсы WebGL.
deckgl.finalize();
Пример:
window.addEventListener('beforeunload', () => {
deckgl.finalize();
});
После вызова метода:
Для крупных проектов часто используется следующая структура:
src/
│
├── data/
│ └── api.js
│
├── layers/
│ ├── points.js
│ ├── polygons.js
│ └── routes.js
│
├── ui/
│ └── tooltip.js
│
├── deck/
│ └── deck-instance.js
│
└── main.js
Экземпляр Deck создаётся один раз:
export const deckgl = new deck.Deck({
parent: document.getElementById('app'),
controller: true
});
Каждый слой формируется отдельной функцией:
export function createPointLayer(data) {
return new deck.ScatterplotLayer({
id: 'points',
data,
getPosition: d => d.position
});
}
Сборка сцены:
deckgl.setProps({
layers: [
createPolygonLayer(polygons),
createLineLayer(routes),
createPointLayer(points)
]
});
Подобная организация позволяет использовать Deck.gl в крупных приложениях на чистом JavaScript без React, сохраняя модульность, высокую производительность и полный контроль над жизненным циклом визуализации.