Аналитика в Mapbox GL JS строится вокруг событийной модели карты, состояния вьюпорта и взаимодействий пользователя с рендерингом WebGL-сцены. Библиотека не навязывает единый аналитический стек, но предоставляет набор низкоуровневых событий и API, на основе которых выстраиваются системы трекинга поведения, тепловые карты взаимодействий, продуктовые метрики и мониторинг производительности.
Карта в Mapbox GL JS генерирует поток событий, отражающих весь жизненный цикл рендера и пользовательских действий. Эти события являются базой для построения аналитических систем.
Ключевые категории событий:
load,
style.load)render, idle,
data)click,
mousemove, drag, zoom,
rotate)sourcedata,
sourcedata)Типовая регистрация событий:
map.on('load', () => {
console.log('Карта загружена');
});
map.on('click', (e) => {
console.log('Клик по карте', e.lngLat);
});
Каждое событие несёт контекст: координаты, пиксельные позиции, состояние камеры и список объектов под курсором.
Основной слой аналитики строится вокруг пользовательских действий. Карта становится интерактивным интерфейсом, где каждое действие можно интерпретировать как событие продукта.
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point);
analytics.track('map_click', {
coordinates: e.lngLat,
featuresCount: features.length,
featureTypes: features.map(f => f.layer.id)
});
});
Функция queryRenderedFeatures позволяет извлечь объекты,
которые визуально находятся под курсором. Это ключевой механизм
связывания UI-событий с геоданными.
map.on('mousemove', (e) => {
const features = map.queryRenderedFeatures(e.point);
if (features.length) {
analytics.track('map_hover_feature', {
layer: features[0].layer.id
});
}
});
Из-за высокой частоты mousemove обычно применяется
дебаунсинг или семплирование событий.
В Mapbox GL JS камера описывает текущее состояние карты: центр, масштаб, поворот и наклон. Эти параметры используются для анализа поведения пользователя.
function getViewportState(map) {
return {
zoom: map.getZoom(),
center: map.getCenter(),
bearing: map.getBearing(),
pitch: map.getPitch(),
bounds: map.getBounds()
};
}
Типовые сценарии аналитики вьюпорта:
Отслеживание изменения камеры:
map.on('moveend', () => {
analytics.track('viewport_change', getViewportState(map));
});
Аналитика производительности карты строится вокруг событий
render, idle и времени между интеракциями.
render — вызывается при каждом кадре WebGLidle — карта завершила рендеринг и не имеет активных
задачload — завершение загрузки стиляПример измерения времени интерактивности:
const start = performance.now();
map.on('load', () => {
const t = performance.now() - start;
analytics.track('map_load_time', {
duration: t
});
});
Отдельный интерес представляет метрика time-to-idle:
map.on('idle', () => {
analytics.track('map_idle_state', {
timestamp: Date.now()
});
});
Слои в Mapbox GL JS являются основными единицами визуализации. Их можно использовать как аналитические сегменты.
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point);
features.forEach(f => {
analytics.track('layer_interaction', {
layerId: f.layer.id,
source: f.source,
geometryType: f.geometry.type
});
});
});
Типовые метрики:
Feature State позволяет хранить состояние объектов на стороне клиента, что даёт возможность строить интерактивные метрики.
map.setFeatureState(
{ source: 'places', id: 123 },
{ selected: true }
);
Использование:
Аналитика может извлекать частоту изменений состояния:
analytics.track('feature_state_change', {
featureId: 123,
state: 'selected'
});
В Mapbox GL JS можно анализировать не только действия, но и пространственное распределение интереса.
const bounds = map.getBounds();
analytics.track('region_view', {
northEast: bounds.getNorthEast(),
southWest: bounds.getSouthWest(),
zoom: map.getZoom()
});
Применения:
Mapbox GL JS легко интегрируется с системами продуктовой аналитики.
map.on('click', (e) => {
gtag('event', 'map_click', {
event_category: 'map',
event_label: `${e.lngLat.lng},${e.lngLat.lat}`
});
});
map.on('moveend', () => {
analytics.track('map_move', {
zoom: map.getZoom()
});
});
Часто используется промежуточный слой:
function track(eventName, payload) {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify({
event: eventName,
payload,
timestamp: Date.now()
})
});
}
Из-за высокой частоты событий (особенно mousemove и
render) применяются стратегии снижения нагрузки:
Пример:
let buffer = [];
map.on('mousemove', (e) => {
buffer.push(e.lngLat);
if (buffer.length > 20) {
analytics.track('mouse_path', { path: buffer });
buffer = [];
}
});
Библиотека включает встроенную телеметрию использования, которая может быть отключена:
mapboxgl.setTelemetryEnabled(false);
Телеметрия включает агрегированные данные о производительности и использовании функций библиотеки. В аналитических системах это обычно учитывается как внешний системный слой, не связанный с бизнес-метриками.
Источники (sources) позволяют отслеживать загрузку и использование данных:
map.on('sourcedata', (e) => {
if (e.isSourceLoaded) {
analytics.track('source_loaded', {
sourceId: e.sourceId
});
}
});
Метрики:
Комбинация событий move, zoom,
rotate позволяет восстанавливать пользовательские
сценарии:
Пример фиксации навигационного шага:
map.on('moveend', () => {
analytics.track('navigation_step', {
zoom: map.getZoom(),
center: map.getCenter()
});
});
Этот метод является центральным для связывания визуального слоя и данных:
const features = map.queryRenderedFeatures(point, {
layers: ['cities', 'roads']
});
Использование:
События карты часто агрегируются по временным интервалам:
Пример агрегации:
setInterval(() => {
analytics.track('viewport_snapshot', getViewportState(map));
}, 10000);
Координаты событий позволяют строить пространственные распределения:
map.on('click', (e) => {
geoAnalytics.addPoint(e.lngLat);
});
Такие данные часто используются для оптимизации UI: перераспределения подписей, улучшения кластеров и настройки визуальной плотности объектов.