Геолокация на мобильных

Работа с API геолокации в браузере

В основе определения местоположения в мобильных браузерах лежит Geolocation API, предоставляемый средой выполнения JavaScript. Доступ к координатам возможен только при соблюдении ряда условий безопасности: использование HTTPS, явное разрешение пользователя и поддержка устройства.

Основной метод получения позиции:

navigator.geolocation.getCurrentPosition(success, error, options);

Для непрерывного отслеживания:

navigator.geolocation.watchPosition(success, error, options);

Параметры options определяют точность, таймаут и поведение кэширования:

const options = {
  enableHighAccuracy: true,
  timeout: 10000,
  maximumAge: 0
};
  • enableHighAccuracy активирует GPS вместо приблизительных данных Wi-Fi/сети
  • timeout ограничивает время ожидания ответа
  • maximumAge управляет использованием кэшированных координат

Интеграция с Leaflet

Leaflet предоставляет встроенный механизм геолокации через метод map.locate().

Базовая инициализация карты:

const map = L.map('map').setView([0, 0], 2);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors'
}).addTo(map);

Запуск определения местоположения:

map.locate({ setView: true, maxZoom: 16 });

Параметры:

  • setView — автоматически центрирует карту на найденной позиции
  • maxZoom — устанавливает масштаб после определения координат
  • watch — включает непрерывное отслеживание положения

Обработка события успешного определения позиции

Leaflet генерирует событие locationfound:

map.on('locationfound', function (e) {
  const radius = e.accuracy;

  L.marker(e.latlng).addTo(map)
    .bindPopup('Текущая позиция').openPopup();

  L.circle(e.latlng, radius).addTo(map);
});

Объект события содержит ключевые данные:

  • latlng — координаты пользователя
  • accuracy — радиус точности в метрах
  • altitude — высота (если доступна)
  • speed — скорость (на мобильных устройствах с GPS)

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


Обработка ошибок геолокации

При отказе или сбое вызывается событие locationerror:

map.on('locationerror', function (e) {
  console.log(e.message);
});

Типичные причины ошибок:

  • пользователь отклонил доступ
  • устройство не поддерживает геолокацию
  • превышен таймаут запроса
  • отсутствие GPS/сети

Непрерывное отслеживание позиции

Для мобильных сценариев навигации используется режим watch: true:

map.locate({
  watch: true,
  enableHighAccuracy: true
});

В этом режиме карта обновляется при каждом изменении координат.

Обновление маркера:

let userMarker;
let accuracyCircle;

map.on('locationfound', function (e) {
  if (userMarker) {
    map.removeLayer(userMarker);
    map.removeLayer(accuracyCircle);
  }

  userMarker = L.marker(e.latlng).addTo(map);
  accuracyCircle = L.circle(e.latlng, e.accuracy).addTo(map);
});

Остановка отслеживания

Leaflet не предоставляет отдельного метода остановки watch напрямую, поэтому используется API браузера:

const watchId = navigator.geolocation.watchPosition(success, error);

// остановка
navigator.geolocation.clearWatch(watchId);

При этом необходимо хранить watchId вне обработчиков событий.


Мобильные особенности геолокации

На мобильных устройствах поведение геолокации отличается от десктопа:

iOS Safari

  • требует явного взаимодействия пользователя (например, нажатия кнопки)
  • может возвращать неточные координаты без GPS
  • ограничивает фоновые обновления

Android Chrome

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

Центрирование карты на текущей позиции

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

map.on('locationfound', function (e) {
  map.setView(e.latlng, 16);
});

Для предотвращения постоянного “скачка” карты применяется флаг:

let firstFix = true;

map.on('locationfound', function (e) {
  if (firstFix) {
    map.setView(e.latlng, 16);
    firstFix = false;
  }
});

Пользовательский контроль геолокации

Геолокация часто привязывается к UI-кнопке:

const locateBtn = L.control({ position: 'topleft' });

locateBtn.on Add = function () {
  const btn = L.DomUtil.create('button', 'locate-btn');
  btn.innerHTML = '?';

  btn.oncl ick = function () {
    map.locate({ setView: true, maxZoom: 16 });
  };

  return btn;
};

locateBtn.addTo(map);

Повышение точности позиционирования

Для мобильной навигации используется комбинация настроек:

map.locate({
  enableHighAccuracy: true,
  maximumAge: 0,
  timeout: 15000,
  watch: true
});

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


Работа с несколькими источниками данных

В мобильных условиях координаты могут поступать из разных источников:

  • GPS (высокая точность)
  • Wi-Fi позиционирование (средняя точность)
  • сотовые вышки (низкая точность)

Leaflet не управляет источниками напрямую, но корректно отображает accuracy, позволяя визуально оценивать качество данных.


Отображение направления движения

При наличии данных heading можно визуализировать направление:

map.on('locationfound', function (e) {
  if (e.heading !== undefined) {
    console.log('Направление:', e.heading);
  }
});

На практике направление часто нестабильно на низких скоростях и в помещениях.


Адаптация под нестабильный сигнал

При слабом GPS сигнале координаты могут “прыгать”. Для сглаживания используется простая фильтрация:

let lastLatLng;

map.on('locationfound', function (e) {
  if (!lastLatLng) {
    lastLatLng = e.latlng;
    return;
  }

  const distance = map.distance(lastLatLng, e.latlng);

  if (distance < 50) {
    lastLatLng = e.latlng;
    userMarker.setLatLng(e.latlng);
  }
});

Такой подход снижает визуальные скачки маркера.


Использование геолокации для маршрутизации

После получения координат пользовательской позиции они передаются в системы маршрутизации:

function onLocationFound(e) {
  const start = e.latlng;
  const destination = L.latLng(48.8566, 2.3522);
}

Дальнейшая логика обычно строится поверх внешних сервисов маршрутов, а Leaflet используется как слой визуализации.


Особенности работы в фоновом режиме

На мобильных браузерах:

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

Поэтому стабильное отслеживание требует активного экрана и взаимодействия с картой.


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

При отказе в доступе API возвращает код ошибки:

map.on('locationerror', function (e) {
  if (e.code === 1) {
    console.log('Доступ запрещён');
  }
});

Коды:

  • 1 — отказ в разрешении
  • 2 — позиция недоступна
  • 3 — таймаут

Сочетание геолокации и кастомных слоёв

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

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
L.control.scale().addTo(map);

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


Отладка геолокации на мобильных устройствах

Типичные проблемы:

  • отсутствие HTTPS
  • отключён GPS
  • запрет в настройках браузера
  • использование эмуляторов без симуляции координат

Leaflet-события позволяют локализовать проблему:

  • locationfound не вызывается → проблема API
  • locationerror с кодом → ошибка доступа или сети

Поведение при первом запуске карты

Первый вызов геолокации часто задерживается из-за запроса разрешения. В этот момент карта уже должна быть инициализирована, иначе события могут не привязаться.

const map = L.map('map').setView([0, 0], 2);

map.on('locationfound', onLocationFound);
map.on('locationerror', onLocationError);

map.locate();