Geolocation API

Узнаём местоположение пользователя 🧭

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

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

Как пишется

Секция статьи "Как пишется"

Получить доступ к геолокации позволяет свойство navigator.geolocation объекта navigator:

        
          
          navigator.geolocation
          navigator.geolocation

        
        
          
        
      

Как понять

Секция статьи "Как понять"

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

Для этого браузер предлагает своё API. Когда мы воспользуемся свойством navigator.geolocation, в ответе получим интерфейс Geolocation, — он позволяет работать с данными геопозиции:

        
          
          Geolocation {}
          Geolocation {}

        
        
          
        
      

Внутри него:

        
          
          clearWatch: ƒ clearWatch()getCurrentPosition: ƒ getCurrentPosition()watchPosition: ƒ watchPosition()constructor: ƒ Geolocation()Symbol(Symbol.toStringTag): "Geolocation"[[Prototype]]: Object
          clearWatch: ƒ clearWatch()
getCurrentPosition: ƒ getCurrentPosition()
watchPosition: ƒ watchPosition()
constructor: ƒ Geolocation()
Symbol(Symbol.toStringTag): "Geolocation"
[[Prototype]]: Object

        
        
          
        
      

Для Geolocation есть различные методы: getCurrentPosition, watchPosition и clearWatch. Если их вызвать, то пользователь получит уведомление. Например, в Chrome появится следующее диалоговое окно:

Диалоговое окно с запросом местоположения в браузере Chrome

Если человек одобрит запрос, мы получим возможность работать с интерфейсом GeolocationPosition:

        
          
          GeolocationPosition {coords: GeolocationCoordinates, timestamp: 1665141114856}
          GeolocationPosition {coords: GeolocationCoordinates, timestamp: 1665141114856}

        
        
          
        
      

Он включает объект GeolocationCoordinates с данными геолокации пользователя и параметр timestamp со временем получения координат:

        
          
          GeolocationCoordinates {  latitude: 36.01068878173828,  longitude: 37.20875549316406,  altitude: null,  accuracy: 40,  altitudeAccuracy: null,  …}
          GeolocationCoordinates {
  latitude: 36.01068878173828,
  longitude: 37.20875549316406,
  altitude: null,
  accuracy: 40,
  altitudeAccuracy: null,}

        
        
          
        
      

Чаще всего используются широта latitude и долгота longitude. Помимо них в объекте содержатся:

  • altitude — отвечает за высоту в метрах над эллипсоидом (что за эллипсоид под нами?);
  • accuracy — точность широты и долготы в метрах (например, 40 метров);
  • altitudeAccuracy — уровень точности высоты над эллипсоидом в метрах;
  • heading — направление движения. Угол, который отсчитывается по часовой стрелке относительно истинного севера и может принимать значения от 0° до 360°;
  • speed — скорость движения в метрах в секунду.

Как узнать геолокацию единожды

Секция статьи "Как узнать геолокацию единожды"

Чтобы получить координаты один раз, воспользуйтесь методом getCurrentPosition и передайте внутрь колбэк. Его аргументом в случае успеха выступит объект GeolocationPosition:

        
          
          navigator.geolocation.getCurrentPosition(position => {  const { latitude, longitude } = position.coords})// записываем в переменные latitude и longitude координаты пользователя
          navigator.geolocation.getCurrentPosition(position => {
  const { latitude, longitude } = position.coords
})

// записываем в переменные latitude и longitude координаты пользователя

        
        
          
        
      

Кроме колбэка в getCurrentPosition можно передать ещё два аргумента: функцию на случай ошибки и объект с дополнительными опциями:

        
          
          navigator.geolocation.getCurrentPosition(success, error, options)function error() {  alert('Где ты вообще...'); // на случай ошибки}const options = {  enableHighAccuracy: true,  maximumAge: 1000,  timeout: 3600}
          navigator.geolocation.getCurrentPosition(success, error, options)

function error() {
  alert('Где ты вообще...'); // на случай ошибки
}

const options = {
  enableHighAccuracy: true,
  maximumAge: 1000,
  timeout: 3600
}


        
        
          
        
      

Опции помогают настроить запрос детальнее:

  • enableHighAccuracy — просит передавать геолокацию особенно точно, жертвуя энергией устройства и временем;
  • maximumAge — устанавливает время, по истечению которого кэшированную геолокацию следует обновить;
  • timeout — устанавливает временной интервал обновления геолокации.

Наблюдать в динамике

Секция статьи "Наблюдать в динамике"

Если getCurrentPosition позволяет узнать геолокацию единожды, то для наблюдения за постоянно меняющимся местоположением лучше использовать метод watchPosition:

        
          
          navigator.geolocation.watchPosition(position => {  const { latitude, longitude } = position.coords})// постоянно перезаписываем в latitude и longitude координаты пользователя
          navigator.geolocation.watchPosition(position => {
  const { latitude, longitude } = position.coords
})

// постоянно перезаписываем в latitude и longitude координаты пользователя

        
        
          
        
      

Метод watchPosition без конца вызывает колбэк, чтобы данные не застаивались.

Остановить наблюдение

Секция статьи "Остановить наблюдение"

Метод watchPosition возвращает id текущего наблюдения. Его можно использовать в методе clearWatch, чтобы прекратить наблюдение:

        
          
          const geoId = navigator.geolocation.watchPosition(position => {  // наблюдаем за геолокацией и храним в geoId идентификатор})function geoWatchStopper() {  navigator.geolocation.clearWatch(geoId)  // останавливаем наблюдение}
          const geoId = navigator.geolocation.watchPosition(position => {
  // наблюдаем за геолокацией и храним в geoId идентификатор
})

function geoWatchStopper() {
  navigator.geolocation.clearWatch(geoId)
  // останавливаем наблюдение
}

        
        
          
        
      

Как обработать ошибки

Секция статьи "Как обработать ошибки"

В методы getCurrentPosition и watchPosition можно передать колбэк на случай ошибок. За них отвечает объект GeolocationPositionError, его удобно обрабатывать через конструкцию switch:

        
          
          function handleError(error) {  // эту фукнцию можно передать колбэком на случай ошибок  const { code } = error  switch (code) {    case GeolocationPositionError.TIMEOUT:      // время получения геолокации истекло      break    case GeolocationPositionError.PERMISSION_DENIED:      // пользователь запретил трекинг своей геопозиции      break    case GeolocationPositionError.POSITION_UNAVAILABLE:      // получить местоположение не удалось      break  }}
          function handleError(error) {
  // эту фукнцию можно передать колбэком на случай ошибок

  const { code } = error

  switch (code) {
    case GeolocationPositionError.TIMEOUT:
      // время получения геолокации истекло
      break
    case GeolocationPositionError.PERMISSION_DENIED:
      // пользователь запретил трекинг своей геопозиции
      break
    case GeolocationPositionError.POSITION_UNAVAILABLE:
      // получить местоположение не удалось
      break
  }
}

        
        
          
        
      

На практике

Секция статьи "На практике"

Алексей Никитченко советует

Секция статьи "Алексей Никитченко советует"

🛠 С помощью Geolocation API можно получить координаты пользователя, а после найти по ним место на карте. Для этого создадим небольшую функцию, которая соберёт ссылку с долготой и широтой, а после вставим её в iframe c картой:

        
          
          button.addEventListener('click', findLocation) // на клик по кнопке ищем локациюfunction findLocation() {  if (!navigator.geolocation) {    status.textContent = 'Ваш браузер не дружит с геолокацией...'  } else {    navigator.geolocation.getCurrentPosition(success, error)  }  function success(position) {  // если всё хорошо, собираем ссылку    const { longitude, latitude }  = position.coords    map.src = `https://www.openstreetmap.org/export/embed.html?bbox=${longitude}%2C${latitude}&layer=mapnik`  }  function error() { // если всё плохо, просто напишем об этом    status.textContent = 'Не получается определить вашу геолокацию :('  }}
          button.addEventListener('click', findLocation) // на клик по кнопке ищем локацию

function findLocation() {
  if (!navigator.geolocation) {
    status.textContent = 'Ваш браузер не дружит с геолокацией...'
  } else {
    navigator.geolocation.getCurrentPosition(success, error)
  }

  function success(position) {  // если всё хорошо, собираем ссылку
    const { longitude, latitude }  = position.coords

    map.src = `https://www.openstreetmap.org/export/embed.html?bbox=${longitude}%2C${latitude}&layer=mapnik`
  }

  function error() { // если всё плохо, просто напишем об этом
    status.textContent = 'Не получается определить вашу геолокацию :('
  }
}

        
        
          
        
      

Если кликнуть по кнопке, карта приблизится к вашему местоположению:

Открыть демо в новой вкладке

🛠 Удобно проверить в самом начале, есть ли у нас возможность работать с геолокацией. Для этого в нашей функции findLocation есть следующая конструкция:

        
          
          if (!navigator.geolocation) {  status.textContent = 'Ваш браузер не дружит с геолокацией...'} else {  navigator.geolocation.getCurrentPosition(success, error)}
          if (!navigator.geolocation) {
  status.textContent = 'Ваш браузер не дружит с геолокацией...'
} else {
  navigator.geolocation.getCurrentPosition(success, error)
}

        
        
          
        
      

navigator.geolocation принимает значения типа boolean, так что если с геолокацией нельзя поработать, мы можем сразу сообщить об этом. Но если всё хорошо, то остаётся лишь запросить геолокацию и передать её колбэкам 🙂