В визуализациях поверх карт и произвольных координатных систем иконки
и маркеры выступают базовым способом представления дискретных объектов.
В Deck.gl для этих целей используется набор специализированных слоёв,
среди которых ключевую роль играет IconLayer, а также
вспомогательные подходы через ScatterplotLayer и
TextLayer. Архитектура библиотеки ориентирована на
высокопроизводительный рендеринг через WebGL, поэтому даже большое
количество маркеров обрабатывается на GPU, а не на CPU.
Любой слой с маркерами в Deck.gl опирается на массив объектов данных. Каждый объект обычно содержит координаты и дополнительные визуальные свойства.
Типичный формат:
const data = [
{
position: [71.4304, 51.1282],
name: "Объект A",
type: "station",
size: 1
},
{
position: [71.4500, 51.1200],
name: "Объект B",
type: "station",
size: 2
}
];
Ключевой элемент — position, представляющий координаты в
формате [longitude, latitude]. Для 3D-визуализаций
добавляется третья координата высоты [lng, lat, z].
IconLayer предназначен для рендеринга спрайтовых иконок,
собранных в атлас (sprite atlas). Это наиболее производительный способ
отображения большого количества однотипных маркеров.
import {IconLayer} from '@deck.gl/layers';
const iconLayer = new IconLayer({
id: 'icon-layer',
data,
pickable: true,
iconAtlas: '/icons/atlas.png',
iconMapping: {
station: {x: 0, y: 0, width: 32, height: 32},
bus: {x: 32, y: 0, width: 32, height: 32}
},
getIcon: d => d.type,
getPosition: d => d.position,
getSize: d => d.size || 24,
sizeScale: 1,
sizeUnits: 'pixels'
});
iconAtlas — это изображение, содержащее набор иконок в
виде сетки или произвольного размещения. Использование атласа
минимизирует количество текстурных переключений на GPU.
iconMapping описывает координаты каждой иконки внутри
атласа:
iconMapping: {
airport: {
x: 0,
y: 0,
width: 64,
height: 64,
anchorY: 32
},
train: {
x: 64,
y: 0,
width: 64,
height: 64,
anchorY: 32
}
}
Параметр anchorY управляет точкой привязки, что особенно
важно для маркеров, которые должны «стоять» на координате нижней
частью.
Функция getIcon определяет, какую иконку использовать
для каждого объекта:
getIcon: d => {
if (d.type === 'airport') return 'airport';
if (d.type === 'train') return 'train';
return 'default';
}
Это позволяет динамически сопоставлять данные и визуальные представления без изменения атласа.
getSize: d => d.size,
sizeScale: 10
getSize задаёт базовый размер, а sizeScale
определяет глобальный коэффициент. В сочетании они позволяют управлять
визуальной иерархией объектов.
meters — размер в реальных метрахpixels — фиксированный размер на экранеsizeUnits: 'meters'
Использование метров важно при работе с 3D-картами, где объекты должны сохранять масштаб относительно земли.
По умолчанию иконки в Deck.gl используют режим billboard — они всегда повернуты к камере.
billboard: true
Это обеспечивает читаемость независимо от угла обзора. В 3D-сценах можно отключать billboard для создания эффектов пространственного размещения объектов.
Хотя иконки обычно задаются через текстуры, Deck.gl позволяет применять цветовые фильтры:
getColor: d => [255, 0, 0, 200]
Это работает как умножение цвета пикселей текстуры на заданный RGBA-вектор.
Для простых маркеров без текстур используется
ScatterplotLayer. Он эффективен при визуализации точек, где
не требуется уникальная графика.
import {ScatterplotLayer} from '@deck.gl/layers';
const scatter = new ScatterplotLayer({
id: 'scatter',
data,
getPosition: d => d.position,
getRadius: d => d.size * 100,
getFillColor: d => [0, 128, 255, 180],
pickable: true
});
Этот слой рисует окружности, которые могут масштабироваться в мировых координатах или пикселях.
Часто иконки сопровождаются текстом. Для этого используется
TextLayer.
import {TextLayer} from '@deck.gl/layers';
const textLayer = new TextLayer({
id: 'text',
data,
getPosition: d => d.position,
getText: d => d.name,
getSize: 16,
getColor: [0, 0, 0, 255],
getAngle: 0,
billboard: true
});
Комбинация IconLayer + TextLayer является стандартным
паттерном построения интерактивных карт.
Deck.gl построен на концепции композиции слоёв. Маркеры редко используются изолированно — чаще они объединяются в стек:
const layers = [
iconLayer,
scatter,
textLayer
];
Каждый слой рендерится независимо, но использует общую систему координат и камеру.
Основное преимущество Deck.gl — перенос вычислений на GPU. При работе с маркерами это выражается в следующих оптимизациях:
Даже десятки тысяч маркеров могут отображаться без деградации FPS при корректной настройке слоёв.
Deck.gl поддерживает различные системы координат:
COORDINATE_SYSTEM.LNGLAT — географические
координатыCOORDINATE_SYSTEM.METER_OFFSETS — локальные метрыCOORDINATE_SYSTEM.CARTESIAN — произвольные сценыДля маркеров на карте чаще всего используется LNGLAT,
где данные интерпретируются через проекцию Web Mercator.
Параметр pickable включает обработку событий наведения и
клика.
const layer = new IconLayer({
...
pickable: true,
onClick: info => {
console.log(info.object);
}
});
Объект info содержит данные слоя, координаты курсора и
пиксельные позиции, что позволяет строить интерактивные интерфейсы
поверх карты.
Deck.gl использует реактивную модель: изменение данных приводит к перерендеру слоя.
setData(newData);
При этом GPU-пайплайн перестраивается минимально, если структура данных остаётся совместимой.
iconMapping для используемых ключейpixels вместо meters в
3D-сценахsizeUnits: 'meters' для масштабируемых
сценpickable, если интерактивность не
требуетсяВ 3D-режиме маркеры могут располагаться на разной высоте:
getPosition: d => [d.lng, d.lat, d.height]
Это позволяет строить визуализации городских моделей, где иконки представляют здания, объекты инфраструктуры или события на разных уровнях пространства.
Для продвинутых сценариев IconLayer может быть расширен
через шейдерные модификации. Это позволяет реализовать эффекты:
Deck.gl предоставляет shaderModules для внедрения
GLSL-кода без полного переписывания слоя.
При росте количества объектов важным становится переход от индивидуальных маркеров к агрегированным представлениям:
Тем не менее IconLayer остаётся базовым элементом, на
который опираются более сложные визуальные конструкции.