Стилизация в Deck.gl определяет визуальное представление геоданных на карте. Цвета, размеры, прозрачность, форма объектов, контуры, высота экструзии и анимация формируют восприятие пространственной информации и позволяют акцентировать внимание на наиболее важных характеристиках набора данных.
Архитектура библиотеки построена таким образом, что практически любой визуальный параметр слоя может быть настроен через специальные свойства (accessors), вычисляемые для каждого объекта данных отдельно. Благодаря этому карта может динамически менять внешний вид в зависимости от атрибутов данных, масштаба карты, состояния взаимодействия пользователя и внешних событий.
Каждый слой Deck.gl содержит набор параметров отображения. Часть параметров задаётся фиксированными значениями:
new ScatterplotLayer({
id: 'points',
data,
getFillColor: [255, 0, 0],
getRadius: 100
})
В этом случае все объекты получают одинаковый цвет и размер.
Другой подход предполагает вычисление стиля для каждого элемента:
new ScatterplotLayer({
id: 'points',
data,
getFillColor: d => d.color,
getRadius: d => d.population
})
Здесь визуальные характеристики определяются содержимым объекта данных.
Такой механизм называется data-driven styling — стилизация на основе данных.
Большинство слоёв используют цвет в формате массива:
[r, g, b]
или
[r, g, b, a]
где:
| Компонент | Диапазон |
|---|---|
| Red | 0–255 |
| Green | 0–255 |
| Blue | 0–255 |
| Alpha | 0–255 |
Пример:
[255, 100, 50]
Оранжевый цвет.
Полупрозрачный вариант:
[255, 100, 50, 120]
Чем меньше значение Alpha, тем прозрачнее объект.
Во многих слоях применяется свойство:
getFillColor
Например:
new ScatterplotLayer({
id: 'cities',
data,
getPosition: d => d.coordinates,
getFillColor: [0, 128, 255]
})
Все точки будут окрашены в синий цвет.
Динамическое вычисление:
getFillColor: d => {
if (d.population > 1000000) {
return [255, 0, 0];
}
return [0, 180, 0];
}
Крупные города отображаются красным цветом, остальные — зелёным.
Одним из наиболее распространённых способов визуализации является отображение числовых показателей через градиент.
Пример:
getFillColor: d => {
const value = d.temperature;
return [
value * 2,
50,
255 - value * 2
];
}
Рост температуры изменяет цвет объекта от синего к красному.
Для более качественного отображения часто используются шкалы из библиотек D3:
import {scaleSequential} from 'd3-scale';
import {interpolateTurbo} from 'd3-scale-chromatic';
const colorScale = scaleSequential(interpolateTurbo)
.domain([0, 100]);
Использование:
getFillColor: d => {
const color = colorScale(d.value);
return [
color.r,
color.g,
color.b
];
}
Такой подход позволяет создавать профессиональные картографические палитры.
Для объектов с контурами применяется свойство:
getLineColor
Пример:
new PolygonLayer({
id: 'regions',
data,
stroked: true,
filled: true,
getLineColor: [0, 0, 0]
})
Контур полигона будет чёрным.
Динамическая настройка:
getLineColor: d =>
d.selected
? [255, 0, 0]
: [80, 80, 80]
Выбранные объекты выделяются красным цветом.
Для линий и контуров используется:
getLineWidth
Пример:
new PathLayer({
id: 'roads',
data,
getPath: d => d.path,
getLineWidth: 5
})
Динамическая толщина:
getLineWidth: d => d.trafficLevel
Ширина дороги зависит от интенсивности движения.
Чтобы толщина не зависела от масштаба карты:
widthUnits: 'meters'
или
widthUnits: 'pixels'
| Значение | Описание |
|---|---|
| pixels | Экранные пиксели |
| meters | Реальные метры |
| common | Внутренние координаты Deck.gl |
Для точечных слоёв используется:
getRadius
Пример:
new ScatterplotLayer({
data,
getRadius: 500
})
Размер определяется в метрах.
Динамическая настройка:
getRadius: d => d.population / 100
Большие города получают более крупные маркеры.
Для ограничения размеров применяются:
radiusMinPixels
и
radiusMaxPixels
Пример:
radiusMinPixels: 2,
radiusMaxPixels: 50
Даже при сильном изменении масштаба объекты остаются читаемыми.
Прозрачность помогает отображать плотные наборы данных без визуальной перегрузки.
Пример:
getFillColor: [0, 128, 255, 80]
Или динамически:
getFillColor: d => [
0,
128,
255,
d.opacity
]
Прозрачность особенно полезна для:
PolygonLayer предоставляет большое количество параметров оформления.
Базовый пример:
new PolygonLayer({
id: 'districts',
data,
getPolygon: d => d.geometry,
filled: true,
stroked: true,
getFillColor: [50, 150, 255],
getLineColor: [0, 0, 0],
getLineWidth: 2
})
Основные свойства:
| Свойство | Назначение |
|---|---|
| filled | Отрисовка заливки |
| stroked | Отрисовка контура |
| extruded | Включение 3D-экструзии |
| wireframe | Каркасное отображение |
| getElevation | Высота объекта |
Одним из преимуществ Deck.gl является работа с WebGL и поддержка объёмных объектов.
Пример:
new PolygonLayer({
data,
extruded: true,
getElevation: d => d.population
})
Высота полигона определяется населением.
Одновременно можно использовать цветовую кодировку:
getFillColor: d => {
const value = d.population;
return [
value / 1000,
100,
255 - value / 1000
];
}
Высота и цвет начинают отражать один и тот же показатель разными визуальными средствами.
Для экструзии важную роль играет освещение.
Deck.gl поддерживает:
Пример создания набора источников света:
import {
AmbientLight,
DirectionalLight,
LightingEffect
} from '@deck.gl/core';
const ambientLight = new AmbientLight({
intensity: 1.0
});
const directionalLight = new DirectionalLight({
direction: [-1, -3, -1],
intensity: 1.5
});
const lightingEffect = new LightingEffect({
ambientLight,
directionalLight
});
Подключение:
new Deck({
effects: [lightingEffect]
});
Грамотно настроенное освещение значительно улучшает читаемость объёмных карт.
Deck.gl поддерживает интерактивное изменение стиля.
Активация:
pickable: true
Обработчик:
onHover: info => {
console.log(info.object);
}
Изменение цвета:
getFillColor: d =>
d.id === hoveredId
? [255, 0, 0]
: [0, 128, 255]
Такой подход используется для:
Deck.gl оптимизирует рендеринг и не пересчитывает стили без необходимости.
Если стиль зависит от внешней переменной:
let selectedCategory;
Следует использовать:
updateTriggers: {
getFillColor: [selectedCategory]
}
Пример:
new ScatterplotLayer({
data,
getFillColor: d =>
d.category === selectedCategory
? [255, 0, 0]
: [0, 128, 255],
updateTriggers: {
getFillColor: [selectedCategory]
}
})
Без updateTriggers слой может не обновить отображение.
Наиболее распространённые подходы:
const colors = {
city: [0, 120, 255],
village: [0, 180, 0],
industrial: [255, 120, 0]
};
Использование:
getFillColor: d => colors[d.type]
Подходит для дискретных значений.
0 → светлый цвет
100 → тёмный цвет
Используется для:
Пример:
Синий ← 0 → Красный
Подходит для отображения отклонений от среднего значения.
Примеры:
ArcLayer применяется для отображения связей между точками.
Пример:
new ArcLayer({
id: 'flights',
data,
getSourcePosition: d => d.from,
getTargetPosition: d => d.to,
getSourceColor: [0, 128, 255],
getTargetColor: [255, 0, 0]
})
Динамический стиль:
getWidth: d => d.passengers / 1000
Толщина дуги отражает объём перевозок.
Для отображения маршрутов используются свойства:
getColor
и
getWidth
Пример:
new PathLayer({
data,
getPath: d => d.path,
getColor: [255, 0, 0],
getWidth: 5
})
Цвет может зависеть от типа маршрута:
getColor: d => {
switch (d.type) {
case 'highway':
return [255, 0, 0];
case 'street':
return [255, 255, 0];
default:
return [180, 180, 180];
}
}
Некоторые визуальные параметры можно изменять во времени.
Пример:
getRadius: d =>
d.baseRadius + animationValue
Где:
animationValue = Math.sin(time) * 100;
Создаётся эффект пульсации маркеров.
Анимация применяется для:
На одной карте рекомендуется использовать не более 5–7 основных цветов. Избыточное количество оттенков затрудняет восприятие данных.
Для отображения плотности объектов часто эффективнее снижать непрозрачность, чем увеличивать насыщенность цвета.
Если красный цвет обозначает высокий риск, такое значение должно сохраняться во всех слоях карты.
Светлые данные лучше отображаются на тёмной подложке, а тёмные — на светлой. Недостаточный контраст существенно ухудшает читаемость.
Размеры объектов должны оставаться различимыми на разных уровнях
приближения. Для этого используются ограничения через
radiusMinPixels, radiusMaxPixels,
widthMinPixels и widthMaxPixels.
Тени, контуры, яркие цвета и объёмная экструзия должны применяться только тогда, когда они действительно помогают интерпретировать данные. Избыточное количество визуальных эффектов снижает информативность карты и усложняет анализ пространственной информации.