Клавиша / esc

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, так что если с геолокацией нельзя поработать, мы можем сразу сообщить об этом. Но если всё хорошо, то остаётся лишь запросить геолокацию и передать её колбэкам 🙂