Архитектура взаимодействия с картой в Mapbox GL JS построена вокруг событийной модели, в которой все пользовательские действия, изменения состояния карты и внутренние процессы рендеринга транслируются в поток событий. Этот механизм обеспечивает контроль над поведением карты без необходимости вмешиваться в рендеринговый цикл WebGL.
Экземпляр карты в Mapbox GL JS реализует интерфейс событийного эмиттера. Основные методы работы с событиями:
map.on(type, listener) — регистрация обработчикаmap.once(type, listener) — одноразовый обработчикmap.off(type, listener) — удаление обработчикаСобытия делятся на несколько категорий:
Каждое событие передаёт объект с контекстной информацией: координаты, состояние карты, целевые объекты (features), DOM-данные и внутренние параметры рендера.
Жизненный цикл карты отражает этапы инициализации и готовности рендера.
loadСрабатывает после полной загрузки стиля, тайлов и ресурсов. На этом этапе карта готова к добавлению слоёв и источников данных.
map.on('load', () => {
map.addSource('points', {
type: 'geojson',
data: '/data/points.geojson'
});
});
style.loadВозникает при загрузке или смене стиля карты. Используется при динамической смене тем или визуальных конфигураций.
idleСигнализирует о завершении всех рендеринговых операций и отсутствии активных изменений. Полезно для выполнения действий после стабилизации карты.
Движение карты включает панорамирование, масштабирование и вращение. Эти события часто используются для синхронизации интерфейсов.
moveВызывается при любом изменении центра карты.
zoomСрабатывает при изменении масштаба.
rotateФиксирует изменение угла поворота.
pitchОтражает изменение наклона камеры.
moveend,
zoomend, rotateendЗавершающие события, фиксирующие окончание соответствующих трансформаций.
Пример отслеживания координат:
map.on('move', () => {
const center = map.getCenter();
console.log(center.lng, center.lat);
});
Слой взаимодействия формируется поверх WebGL и обрабатывает события указателя (mouse/touch/pointer).
clickdblclickmousedownmouseupmousemovemouseentermouseleavecontextmenutouchstarttouchendКаждое событие содержит:
lngLat — географические координатыpoint — пиксельные координатыoriginalEvent — исходное DOM-событиеПример обработки клика:
map.on('click', (e) => {
console.log(e.lngLat);
});
Mapbox GL JS поддерживает привязку событий непосредственно к слоям, что позволяет обрабатывать взаимодействие с конкретными объектами карты.
map.on('click', 'cities-layer', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['cities-layer']
});
console.log(features);
});
Типы событий для слоёв:
clickmouseentermouseleavemousemovemousedownmouseupОсобенность слоя — событие срабатывает только при попадании курсора на отрисованные фичи данного слоя.
При взаимодействии с векторными данными событие содержит массив
объектов features.
Каждый feature включает:
idgeometrypropertieslayersourceПример извлечения данных:
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point);
if (features.length) {
console.log(features[0].properties);
}
});
Источники (sources) генерируют события при изменении данных или их загрузке.
sourcedata — изменение данных источникаdata — обновление данных тайловdataloading — начало загрузкиstyledata — изменение стиля, влияющее на источникиПример контроля загрузки:
map.on('dataloading', (e) => {
console.log('Загрузка данных:', e.sourceId);
});
Эти события используются для мониторинга состояния рендера и обработки ошибок.
errorСрабатывает при возникновении ошибки в загрузке ресурсов или рендеринге.
map.on('error', (e) => {
console.error(e.error);
});
renderВызывается при каждом кадре отрисовки WebGL. Используется для анимаций и синхронизации внешних эффектов.
Mapbox GL JS интерпретирует положение курсора относительно слоя карты и генерирует события наведения.
mouseenter — вход курсора в область слояmouseleave — выход курсораmouseover / mouseout — аналог
DOM-логикиВажно учитывать, что эти события зависят от наличия интерактивных слоёв и могут не срабатывать при отсутствии рендеренных объектов.
События обрабатываются в порядке:
originalEvent)Отсутствует классическая модель bubbling как в DOM, но существует логика приоритета слоёв: верхние визуально слои имеют более высокий приоритет обработки.
Объект события может включать:
lngLat)point)target)originalEvent)features, при layer events)Это позволяет строить сложные сценарии взаимодействия, например:
При динамическом создании интерфейсов важно удалять обработчики:
function onClick(e) {
console.log(e.lngLat);
}
map.on('click', onClick);
map.off('click', onClick);
Использование once полезно для одноразовых операций,
например ожидания загрузки:
map.once('load', () => {
console.log('Карта готова');
});
События mousemove и render могут вызываться
десятки раз в секунду. Их обработка требует оптимизации:
requestAnimationFrameОсобенно критично это при обработке большого числа features или при работе с тяжелыми слоями.
События предоставляют уже готовые координаты, но часто требуется преобразование:
map.project(lngLat) — географические → пиксельныеmap.unproject(point) — пиксельные → географическиеЭто используется при синхронизации UI-элементов с картой:
map.on('move', () => {
const center = map.project(map.getCenter());
console.log(center);
});
События движения и взаимодействия неразрывно связаны с WebGL-циклом рендеринга. Каждый интерактивный жест:
render и idleТаким образом, событийная модель является связующим слоем между UI и графическим движком, реализованным внутри Mapbox экосистемы.