События взаимодействия с пользователем

Система событий в Mapbox GL JS построена на расширенной модели событий, включающей взаимодействие с картой, слоями, источниками данных и DOM-подобными элементами внутри WebGL-контекста. Архитектура событий позволяет обрабатывать как низкоуровневые действия (движение мыши, прокрутка, касания), так и высокоуровневые события геообъектов (клик по слою, наведение на фичу, выбор объектов).


Событийная система базируется на паттерне подписки:

  • регистрация обработчиков через map.on(type, handler)
  • удаление через map.off(type, handler)
  • одноразовые обработчики через map.once(type, handler)

События делятся на несколько категорий:

  • события состояния карты (render lifecycle)
  • события устройства ввода (pointer, mouse, touch, wheel)
  • события взаимодействия с геообъектами (layers, features)
  • события источников данных (sources)
  • события ошибок и диагностики

Каждое событие передаёт объект события, содержащий контекст: координаты, пиксельные позиции, список затронутых объектов, состояние камеры и другие параметры.


События устройства ввода

mouse events

Основной набор событий мыши:

  • mousedown
  • mouseup
  • click
  • dblclick
  • mousemove
  • mouseover
  • mouseout
  • contextmenu

Эти события работают на уровне canvas-контейнера карты. При этом координаты события доступны как:

  • event.point — пиксельные координаты
  • event.lngLat — географические координаты

Ключевая особенность заключается в том, что события мыши могут быть связаны с географическими объектами через выборку фич на текущем слое.


touch events

Для мобильных устройств используются:

  • touchstart
  • touchend
  • touchcancel

Жесты масштабирования и вращения не представлены как отдельные touch-события, а обрабатываются через абстракцию камеры.


wheel event

Событие прокрутки:

  • wheel

Используется для управления zoom камеры. Содержит данные о скорости прокрутки, направлении и инерции. Внутри Mapbox GL JS это событие часто перехватывается для управления плавностью масштабирования.


События камеры

Камера карты — центральная абстракция отображения. Изменения её состояния генерируют следующие события:

  • movestart
  • move
  • moveend
  • zoomstart
  • zoom
  • zoomend
  • rotatestart
  • rotate
  • rotateend
  • pitchstart
  • pitch
  • pitchend

Каждая группа событий имеет структуру:

  • start — начало взаимодействия
  • промежуточное состояние — непрерывное обновление
  • end — завершение действия

Эти события критичны для синхронизации UI: анимации, обновления данных, запросов к API.


События жизненного цикла карты

Система рендера WebGL генерирует события состояния:

  • load — карта и стили загружены
  • render — каждый кадр отрисовки
  • idle — отсутствие активных изменений
  • error — ошибка рендеринга или загрузки ресурсов

Особое значение имеет idle, сигнализирующий о завершении всех асинхронных операций: загрузки тайлов, изображений, данных источников.


События слоёв и фич

Одной из ключевых возможностей является обработка событий на уровне слоёв:

map.on('click', 'layer-id', (e) => {
  console.log(e.features);
});

Поддерживаются события:

  • click
  • mouseenter
  • mouseleave
  • mousemove
  • mousedown
  • mouseup

При этом система выполняет выборку объектов под курсором через:

  • queryRenderedFeatures
  • querySourceFeatures

Каждое событие слоя содержит:

  • features — массив геообъектов
  • layer — идентификатор слоя
  • point — координаты пикселя
  • lngLat — географические координаты

Hover-состояния и управление выделением

Для реализации интерактивных эффектов наведения используется комбинация событий:

  • mouseenter
  • mouseleave
  • mousemove

Типичный паттерн включает хранение текущего выделенного объекта и обновление визуального состояния слоя.

Оптимизированный подход предполагает использование:

  • setFeatureState
  • getFeatureState

Пример логики:

  • при входе курсора на объект устанавливается состояние hover: true
  • при выходе — сбрасывается состояние

Это позволяет избегать пересоздания источников данных и минимизировать перерендер.


Работа с состоянием объектов (Feature State)

Feature State используется для хранения интерактивных состояний без изменения исходных данных:

  • hover
  • selected
  • active
  • filtered

События взаимодействия часто комбинируются с этим механизмом:

  • mousemove → обновление hover
  • click → установка selected
  • mouseleave → сброс состояния

Важное свойство — состояние привязано к source и id, а не к визуальному объекту.


Прерывание и распространение событий

Система допускает управление распространением событий:

  • stopPropagation() — блокировка дальнейшей обработки
  • приоритет слоёв влияет на порядок обработки
  • верхние слои получают события первыми

Это особенно важно при перекрывающихся слоях, где несколько геообъектов находятся под курсором.


События drag и взаимодействие с картой

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

  • mousedown / touchstart
  • dragstart
  • drag
  • dragend

Drag-события тесно связаны с камерой, так как изменяют center, bearing, pitch.

Также используются:

  • инерция перемещения
  • ограничение границ (bounds constraint)
  • damping эффект

События выбора объектов

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

  • click по слою
  • queryRenderedFeatures в точке клика

Событие возвращает массив объектов, так как под курсором может находиться несколько фич.

Стратегии обработки:

  • выбор верхнего слоя
  • агрегация результатов
  • фильтрация по свойствам

Обработка координат в событиях

Каждое интерактивное событие содержит два ключевых представления позиции:

  • экранное пространство (point)
  • географическое пространство (lngLat)

Преобразования между ними позволяют:

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

Производительность событийной модели

При интенсивных взаимодействиях (mousemove, touchmove) возникает высокая частота событий.

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

  • throttling обработчиков движения
  • использование requestAnimationFrame
  • минимизация вызовов queryRenderedFeatures
  • кэширование результатов под курсором

Дополнительно применяется разделение логики:

  • визуальные эффекты
  • бизнес-логика
  • запросы данных

События ошибок

Система генерирует error при:

  • загрузке тайлов
  • ошибках стилей
  • недоступности источников
  • проблемах WebGL

Объект ошибки содержит:

  • код
  • сообщение
  • контекст источника

События источников данных

Источники (sources) генерируют события:

  • sourcedata
  • data
  • dataloading

Они позволяют отслеживать:

  • загрузку тайлов vector/raster
  • обновление GeoJSON
  • кеширование данных

Комбинирование событий для сложной интерактивности

Сложные сценарии строятся через комбинации:

  • hover + feature state
  • click + popup
  • move + динамическая фильтрация
  • zoom + кластеризация данных

Пример логики взаимодействия:

  • mousemove определяет активный объект
  • click фиксирует выбор
  • zoomend пересчитывает кластерные группы
  • idle запускает фоновые обновления

Контекст событий и объект MapMouseEvent

Большинство пользовательских событий наследуются от базового класса событий карты и содержат:

  • type
  • target
  • originalEvent
  • lngLat
  • point
  • features

Эта структура обеспечивает унифицированный доступ к данным вне зависимости от источника события.


Интерактивные слои как основа событийной модели

Слои в Mapbox GL JS являются основным уровнем, на котором строится интерактивность:

  • каждый слой может быть интерактивным
  • порядок слоёв определяет приоритет событий
  • фильтры слоя влияют на доступные фичи

События слоя позволяют реализовать UI-поведение без отдельного DOM-слоя поверх карты.


Синхронизация событий и визуального состояния

При высокой интерактивности важна согласованность:

  • состояние карты (camera)
  • состояние данных (features)
  • состояние UI (tooltip, popup)

События выступают связующим слоем, синхронизируя эти уровни в реальном времени через единый event loop WebGL-контекста.