В Deck.gl взаимодействие пользователя с картой строится вокруг механизма picking — процесса определения объектов под курсором и генерации событий наведения и клика. Каждый слой, поддерживающий интерактивность, использует внутренний буфер picking и возвращает структурированную информацию об объекте, над которым произошло событие.
Интерактивность активируется на уровне слоя через свойство
pickable. Без его включения слой не участвует в обработке
событий, даже если он визуально присутствует на сцене. При включённом
pickable Deck.gl отслеживает попадание указателя в
геометрию слоя и формирует объект info, передаваемый в
обработчики.
Система взаимодействия опирается на два основных события:
onHover)onClick)Оба события получают единый объект с информацией о picking:
const layer = new ScatterplotLayer({
id: 'points',
data,
pickable: true,
onHover: info => {
console.log(info);
},
onClick: info => {
console.log(info);
}
});
Структура объекта info содержит ключевые поля:
x, y — экранные координаты курсораcoordinate — географические координаты (если
применимо)object — объект данных, связанный с пиксельным
попаданиемindex — индекс элемента в массиве данныхlayer — ссылка на слой, сгенерировавший событиеviewport — текущее состояние камерыПоле object является центральным элементом: именно оно
связывает визуальный пиксель с исходными данными.
Для корректной работы взаимодействия требуется соблюдение нескольких условий:
new Deck({
initialViewState,
controller: true,
layers: [
new ScatterplotLayer({
id: 'points',
data,
pickable: true
})
]
});
Ключевые параметры, влияющие на поведение picking:
pickable — разрешает участие слоя в событияхautoHighlight — включает автоматическое подсвечивание
объекта при наведенииhighlightColor — цвет подсветкиhighlightedObjectIndex — ручное управление
выделениемАвтоматическое выделение используется в простых сценариях, где не требуется сложная логика UI.
Объект info, передаваемый в обработчики, имеет
детализированную структуру:
{
x: 320,
y: 180,
coordinate: [73.56, 45.12],
object: { id: 1, value: 42 },
index: 10,
layer: ScatterplotLayer,
viewport: WebMercatorViewport,
picked: true
}
Особое значение имеет поле picked. Оно позволяет
отличать пустые события наведения (когда курсор находится над картой, но
не над объектом) от реального попадания.
Событие onHover вызывается при каждом движении курсора.
Это требует контроля частоты обновлений, особенно при сложных слоях и
больших наборах данных.
Типичная проблема — избыточные перерендеры интерфейса при каждом пиксельном смещении. Для её решения применяется мемоизация и фильтрация:
onHover: info => {
if (info.picked) {
updateTooltip(info.object);
} else {
hideTooltip();
}
}
Дополнительно используется сравнение объектов:
let lastObject = null;
onHover: info => {
if (info.object !== lastObject) {
lastObject = info.object;
updateTooltip(info.object);
}
}
Клик обрабатывается аналогично наведению, но имеет более устойчивую семантику — событие считается завершённым действием пользователя.
onClick: info => {
if (!info.picked) {
return;
}
selectFeature(info.object);
}
В сложных сценах возможна конкуренция слоёв за обработку клика. Deck.gl выбирает верхний визуально доступный объект, основываясь на порядке слоёв и их прозрачности.
При работе с мелкими объектами точечный клик может быть
недостаточным. Для расширения области захвата используется
pickingRadius:
new Deck({
controller: true,
pickingRadius: 5,
layers: [
new ScatterplotLayer({
id: 'points',
data,
pickable: true
})
]
});
Увеличение радиуса полезно для плотных кластеров точек, но может приводить к неоднозначности выбора объекта.
Deck.gl предоставляет встроенную поддержку подсказок через
getTooltip:
new Deck({
layers: [
new ScatterplotLayer({
id: 'points',
data,
pickable: true
})
],
getTooltip: ({object}) =>
object && {
html: `<div>${object.name}</div>`,
style: {
backgroundColor: '#fff',
color: '#000'
}
}
});
Tooltip формируется на основе текущего info и
автоматически обновляется при движении курсора.
Поле coordinate в событиях зависит от системы координат
слоя. В географических слоях это обычно
[longitude, latitude], в экранных — пиксельные
координаты.
При использовании кастомных проекций важно учитывать, что
coordinate может быть null, если слой не
поддерживает геопривязку.
В @deck.gl/react события передаются через свойства
компонента DeckGL:
import DeckGL from '@deck.gl/react';
<DeckGL
initialViewState={viewState}
controller
layers={layers}
onCl ick={handleClick}
onHo ver={handleHover}
/>
В этом случае события агрегируются на уровне всей сцены, а не
отдельного слоя. Для определения источника используется поле
layer внутри info.
При перекрытии слоёв важную роль играет порядок их объявления.
Верхний слой имеет приоритет при picking. Однако прозрачность и
visible также влияют на результат.
Для сложных сцен применяется стратегия явного управления интерактивностью:
pickable у фоновых слоёвvisible: false для временного
исключенияОбработка событий напрямую влияет на FPS при интенсивном движении курсора. Основные факторы нагрузки:
Оптимизация включает:
infoonHoverlet lastTime = 0;
onHover: info => {
const now = performance.now();
if (now - lastTime < 16) return;
lastTime = now;
processHover(info);
}
Deck.gl позволяет строить поверх стандартного picking собственные механизмы взаимодействия. Например, группировка объектов или кастомный hit-test на уровне данных:
onClick: info => {
const cluster = findCluster(info.object);
expandCluster(cluster);
}
В таких сценариях info.object становится входной точкой
для дополнительной бизнес-логики, а не конечным результатом выбора.