Выделение объектов

В визуализации больших геоданных ключевую роль играет возможность акцентировать отдельные элементы сцены. В Deck.gl выделение объектов (object picking and highlighting) представляет собой механизм, позволяющий пользователю или системе идентифицировать конкретные геометрические сущности, взаимодействовать с ними и изменять их визуальное представление без перерасчёта всей сцены.

Выделение в Deck.gl опирается на два взаимосвязанных процесса:

  • picking — определение объекта под курсором или в заданной области
  • highlighting — визуальное изменение состояния выбранного объекта

Эти процессы реализуются на уровне слоя (Layer) и тесно связаны с архитектурой рендеринга WebGL.


Механизм picking в архитектуре Deck.gl

Каждый слой Deck.gl при рендеринге может генерировать уникальные идентификаторы для объектов. При включении режима picking библиотека выполняет дополнительный проход рендеринга в offscreen-буфер, где каждый объект кодируется уникальным цветом.

Ключевые характеристики механизма:

  • каждый объект получает уникальный object picking color
  • цвет не отображается пользователю напрямую
  • WebGL-буфер используется только для вычисления попадания курсора
  • результат декодируется обратно в идентификатор объекта

Таким образом, процесс можно представить как:

  1. Рендер сцены в обычном режиме
  2. Рендер сцены в picking-режиме
  3. Чтение пикселя под курсором
  4. Декодирование идентификатора объекта

Событие onHover и onClick как точки входа в выделение

Deck.gl предоставляет встроенные события взаимодействия:

  • onHover — вызывается при наведении курсора
  • onClick — вызывается при клике по объекту

Каждое событие получает объект info, содержащий:

  • object — данные геометрии
  • x, y — координаты курсора
  • coordinate — географические координаты (если применимо)
  • layer — слой, из которого пришёл объект

Структура info является центральной точкой для реализации логики выделения.

Пример типичной обработки:

  • сохранение выбранного объекта в состоянии приложения
  • изменение параметров слоя
  • условное изменение стиля отображения

Highlighting через props слоя

В большинстве стандартных слоёв Deck.gl поддерживается встроенный механизм визуального выделения через свойства highlightedObjectIndex или highlightColor.

Основные подходы:

  • highlightColor — цвет подсветки
  • updateTriggers — контроль пересчёта при изменении состояния
  • getColor / getFillColor — динамическое изменение цвета объекта

Изменение внешнего вида объекта не требует перерасчёта геометрии, только обновления атрибутов рендера.


Использование состояния для управления выделением

Типичный подход основан на хранении состояния выбранного объекта:

  • идентификатор объекта (id)
  • индекс в массиве данных
  • ссылка на объект данных

Состояние передаётся в слой и используется для условной стилизации.

Принцип работы:

  • при событии onHover обновляется временное состояние
  • при onClick фиксируется выбранный объект
  • слой перерисовывается с учётом нового состояния

Реализация выделения через getColor

Одним из наиболее гибких способов является динамическое определение цвета:

  • если объект выбран → применяется highlight-цвет
  • если нет → стандартный цвет

Логика условного рендера:

  • сравнение object.id с selectedId
  • возврат разных цветовых значений

Такой подход используется в слоях:

  • ScatterplotLayer
  • GeoJsonLayer
  • PathLayer
  • PolygonLayer

Оптимизация выделения при больших объёмах данных

При работе с миллионами объектов важно минимизировать стоимость пересчётов.

Основные оптимизационные стратегии:

Использование updateTriggers

Deck.gl пересчитывает атрибуты слоя только при изменении указанных зависимостей.

Ключевой принцип:

  • изменение выделенного объекта должно быть явно привязано к trigger

Минимизация перерасчёта атрибутов

  • не пересчитывать геометрию при каждом hover
  • разделять визуальные и геометрические данные
  • использовать memoization на уровне приложения

Использование инстансинга

Для точечных слоёв применяется instanced rendering, где:

  • геометрия одна
  • данные передаются как атрибуты
  • выделение меняет только атрибут цвета

Pickable и его роль в выделении

Свойство pickable управляет участием слоя в системе picking.

Если pickable: false:

  • слой не участвует в обработке событий
  • объекты не могут быть выделены
  • повышается производительность

Если pickable: true:

  • слой включается в picking-pass
  • генерируются события взаимодействия

Выбор значения зависит от:

  • интерактивности слоя
  • требований к производительности

Manual picking через DeckGL API

Помимо событий, Deck.gl предоставляет API:

  • deck.pickObject()
  • deck.pickMultipleObjects()

Эти методы позволяют:

  • выполнять программное выделение
  • реализовывать сложные сценарии (например, выделение по таймеру или области)
  • интегрировать внешние UI-элементы

Результат аналогичен событию onHover, но вызывается вручную.


Hover-эффекты и временное выделение

Hover-выделение является кратковременным состоянием, которое:

  • активируется при движении мыши
  • сбрасывается при уходе курсора
  • не влияет на глобальное состояние приложения

Часто используется:

  • для подсказок (tooltips)
  • для подсветки маршрутов
  • для визуальной обратной связи

В отличие от click-selection, hover требует высокой производительности, так как события могут происходить десятки раз в секунду.


Сложные сценарии выделения

Множественное выделение

Реализуется через хранение массива идентификаторов:

  • добавление объекта в список
  • удаление по повторному клику
  • поддержка shift/ctrl логики

Выделение групп объектов

Используется при работе с:

  • GeoJSON-кластерами
  • агрегированными данными
  • heatmap-представлениями

Подход:

  • выделяется не объект, а категория или группа
  • визуальное изменение применяется ко всем связанным элементам

Взаимодействие выделения с слоями компоновки

Composite Layers (например, GeoJsonLayer) требуют особого подхода:

  • picking делегируется дочерним слоям
  • highlight может применяться на разных уровнях (feature / geometry / point)
  • необходимо учитывать вложенную структуру данных

Особенность:

  • объект может быть частью сложной геометрии
  • выделение должно учитывать тип feature (Point, LineString, Polygon)

Использование pickingInfo для кастомной логики

Объект pickingInfo содержит расширенные данные:

  • layer
  • index
  • object
  • sourceLayer
  • coordinate

Эти данные позволяют:

  • строить кастомные панели информации
  • реализовывать контекстные действия
  • связывать выделение с внешними системами аналитики

Производственные паттерны выделения

Паттерн «single source of truth»

Все состояния выделения хранятся централизованно:

  • предотвращает рассинхронизацию слоёв
  • упрощает управление UI

Паттерн «derived styling»

Визуальные свойства слоёв вычисляются на основе состояния:

  • уменьшает дублирование логики
  • повышает предсказуемость рендера

Паттерн «stateless layers»

Слои не хранят состояние выделения внутри себя:

  • вся логика находится в приложении
  • слой является функцией от данных

Производительность при частом выделении

Основные узкие места:

  • повторный picking-pass
  • пересчёт атрибутов
  • обновление React state

Методы оптимизации:

  • throttling событий hover
  • разделение слоёв (static / interactive)
  • кэширование результатов picking
  • использование WebGL attribute buffers

Особенности выделения в 3D слоях

В 3D слоях (например, ColumnLayer, HexagonLayer) выделение включает:

  • изменение высоты объекта
  • изменение цвета и эмиссии
  • потенциальное обновление освещения

Важно учитывать:

  • изменение глубины сцены влияет на визуальное восприятие highlight
  • требуется корректная работа depth testing

Связь выделения и tooltip систем

Tooltip в Deck.gl почти всегда строится на основе picking:

  • hover → получение object
  • извлечение атрибутов
  • отображение UI

Ключевая особенность: tooltip не является частью слоя, он внешняя реакция на picking-событие.


Ошибки при реализации выделения

Типовые проблемы:

  • отсутствие pickable: true
  • неправильная работа updateTriggers
  • мутация данных без обновления состояния
  • конфликт hover и click состояний
  • избыточный re-render всей сцены

Каждая из этих ошибок приводит либо к деградации производительности, либо к некорректной визуализации выделения.


Итоговая модель поведения выделения

Внутренне система выделения Deck.gl строится на трёх уровнях:

  • низкоуровневый WebGL picking-pass
  • слойная абстракция обработки событий
  • прикладная логика состояния в приложении

Эта архитектура обеспечивает:

  • масштабируемость до миллионов объектов
  • независимость визуализации от бизнес-логики
  • высокую гибкость кастомизации взаимодействия