События геолокации

MapLibre GL JS предоставляет встроенные механизмы работы с геолокацией пользователя через браузерный API и набор событий, позволяющих отслеживать состояние получения координат, режимы слежения и ошибки. Эти события являются ключевым элементом интерактивных карт, где необходимо отображать позицию пользователя, строить навигацию или реагировать на перемещение в реальном времени.

Геолокация как часть карты

Геолокация в MapLibre GL JS основана на стандартном Web Geolocation API, который предоставляет:

  • текущую позицию пользователя (latitude, longitude)
  • точность определения координат (accuracy)
  • режим непрерывного отслеживания (watchPosition)
  • события ошибок при отсутствии разрешений или недоступности данных

В MapLibre GL JS этот функционал инкапсулирован в GeolocateControl, который автоматически добавляет UI-элемент и генерирует события жизненного цикла геолокации.


GeolocateControl и его события

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

const geolocate = new maplibregl.GeolocateControl({
  positionOptions: {
    enableHighAccuracy: true,
    maximumAge: 0,
    timeout: 6000
  },
  trackUserLocation: true,
  showAccuracyCircle: true,
  showUserLocation: true
});

map.addControl(geolocate);

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


Событие geolocate

Срабатывает при успешном получении координат пользователя. Это базовое событие, на котором строится вся логика отображения позиции.

geolocate.on('geolocate', (position) => {
  console.log('Координаты:', position.coords.longitude, position.coords.latitude);
  console.log('Точность:', position.coords.accuracy);
});

Структура объекта position соответствует стандарту Geolocation API:

  • coords.latitude
  • coords.longitude
  • coords.accuracy
  • coords.heading (если доступно)
  • coords.speed (если доступно)

Типичные сценарии использования:

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

Событие error

Срабатывает при невозможности определить местоположение. Причины могут включать:

  • отказ пользователя в доступе
  • отсутствие GPS
  • таймаут запроса
  • ограничения браузера
geolocate.on('error', (error) => {
  console.error('Ошибка геолокации:', error.message);
});

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

  • code — тип ошибки
  • message — описание
  • PERMISSION_DENIED
  • POSITION_UNAVAILABLE
  • TIMEOUT

События start и end отслеживания

При включённом trackUserLocation геолокация переходит в режим постоянного наблюдения.

trackuserlocationstart

Срабатывает при начале отслеживания:

geolocate.on('trackuserlocationstart', () => {
  console.log('Начато отслеживание пользователя');
});

Используется для:

  • включения UI-индикаторов активности GPS
  • подготовки слоя маршрута
  • активации режимов навигации

trackuserlocationend

Срабатывает при остановке отслеживания:

geolocate.on('trackuserlocationend', () => {
  console.log('Отслеживание остановлено');
});

Типичные причины:

  • пользователь отключил режим
  • потеря сигнала
  • ручное завершение через UI

События обновления позиции

При активном трекинге координаты могут обновляться многократно. В MapLibre GL JS это сопровождается повторными вызовами geolocate.

Практический подход — хранение последнего состояния:

let lastPosition = null;

geolocate.on('geolocate', (position) => {
  lastPosition = position;

  map.flyTo({
    center: [position.coords.longitude, position.coords.latitude],
    speed: 1.2
  });
});

Интеграция с картой и слоями

Геолокационные события часто используются совместно с кастомными слоями:

Маркер пользователя

const userMarker = new maplibregl.Marker()
  .setLngLat([0, 0])
  .addTo(map);

geolocate.on('geolocate', (pos) => {
  userMarker.setLngLat([
    pos.coords.longitude,
    pos.coords.latitude
  ]);
});

Радиус точности

Accuracy circle может быть визуализирован через GeoJSON источник:

geolocate.on('geolocate', (pos) => {
  const radius = pos.coords.accuracy;

  const point = {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [pos.coords.longitude, pos.coords.latitude]
    },
    properties: { radius }
  };

  map.getSource('accuracy').setData(point);
});

Работа с ошибками разрешений

Современные браузеры требуют явного разрешения на геолокацию. Частая ситуация — пользователь отклоняет запрос.

Рекомендуемая обработка:

geolocate.on('error', (err) => {
  if (err.code === err.PERMISSION_DENIED) {
    console.log('Доступ к геолокации запрещён пользователем');
  }
});

В этом случае интерфейс должен переходить в режим ручного выбора точки или поиска адреса.


Управление поведением контроля

GeolocateControl поддерживает программное управление:

geolocate.trigger(); // принудительный запрос геолокации
geolocate.options.trackUserLocation = true;

Также возможно отключение:

geolocate.options.trackUserLocation = false;

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

Геолокация тесно связана с событиями самой карты:

  • move
  • zoom
  • rotate

Пример синхронизации:

geolocate.on('geolocate', (pos) => {
  map.easeTo({
    center: [pos.coords.longitude, pos.coords.latitude],
    zoom: 15
  });
});

Частые архитектурные паттерны

1. Разделение состояния

Геолокация хранится отдельно от UI:

const state = {
  position: null,
  tracking: false
};

geolocate.on('geolocate', (pos) => {
  state.position = pos;
});

2. Event-driven обновления

Использование событий как единственного источника истины:

  • geolocate → обновление state
  • state → обновление слоя карты
  • state → обновление интерфейса

3. Дебаунс частых обновлений

При высокой точности GPS события могут приходить слишком часто:

let timeout;

geolocate.on('geolocate', (pos) => {
  clearTimeout(timeout);

  timeout = setTimeout(() => {
    updateUserPosition(pos);
  }, 200);
});

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

  • геолокация может работать только при HTTPS
  • батарея влияет на частоту обновлений
  • iOS Safari может ограничивать background tracking
  • точность сильно зависит от сети и GPS

Обработка отсутствия поддержки

Некоторые окружения не поддерживают геолокацию:

if (!navigator.geolocation) {
  console.log('Геолокация недоступна');
}

В таких случаях MapLibre GL JS продолжает работу без контроля местоположения.


Связь с пользовательским UX

Геолокационные события влияют на интерфейс:

  • индикатор загрузки координат
  • состояние “поиск местоположения”
  • переключение режима следования за пользователем
  • визуализация точности

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