Geolocation API

We determine the user's location 🧭

Time to read: 5 min

Summary

Geolocation API allows requesting the user's geographical location data.

How to write

Access to geolocation is provided by the navigator.geolocation property of the navigator object:

        
          
          navigator.geolocation
          navigator.geolocation

        
        
          
        
      

How to understand

Sometimes it may be necessary to know where the user is located. For example, we want to show on the map where the nearest pickup point is located.

For this, the browser offers its API. When we use the navigator.geolocation property, we get the Geolocation interface in response, which allows working with geolocation data:

        
          
          Geolocation {}
          Geolocation {}

        
        
          
        
      

Inside it:

        
          
          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

        
        
          
        
      

There are various methods for Geolocation: getCurrentPosition, watchPosition, and clearWatch. If called, the user will receive a notification. For example, in Chrome, the following dialog window will appear:

A dialog window with a location request in the Chrome browser

If the person approves the request, we will have the opportunity to work with the GeolocationPosition interface:

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

        
        
          
        
      

It includes the GeolocationCoordinates object with the user's geolocation data and the timestamp parameter with the time of obtaining the coordinates:

        
          
          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,
  …
}

        
        
          
        
      

Most commonly used are latitude latitude and longitude longitude. In addition to them, the object contains:

  • altitude β€” represents the height in meters above the ellipsoid (what kind of ellipsoid is beneath us?);
  • accuracy β€” the accuracy of latitude and longitude in meters (for example, 40 meters);
  • altitudeAccuracy β€” the level of accuracy of height above the ellipsoid in meters;
  • heading β€” direction of movement. An angle measured clockwise from true north and can take values from 0Β° to 360Β°;
  • speed β€” speed of movement in meters per second.

How to know geolocation once

To obtain coordinates once, use the getCurrentPosition method and pass a callback inside. Its argument in case of success will be the GeolocationPosition object:

        
          
          navigator.geolocation.getCurrentPosition(position => {  const { latitude, longitude } = position.coords})// Store in variables latitude and longitude// the user's coordinates
          navigator.geolocation.getCurrentPosition(position => {
  const { latitude, longitude } = position.coords
})

// Store in variables latitude and longitude
// the user's coordinates

        
        
          
        
      

In addition to the callback, getCurrentPosition can also take two more arguments: a function for error handling and an object with additional options:

        
          
          navigator.geolocation.getCurrentPosition(success, error, options)function error() {  alert('Where are you...') // In case of an error}const options = {  enableHighAccuracy: true,  maximumAge: 1000,  timeout: 3600}
          navigator.geolocation.getCurrentPosition(success, error, options)

function error() {
  alert('Where are you...') // In case of an error
}

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

        
        
          
        
      

Options help to configure the request in more detail:

  • enableHighAccuracy β€” requests transmitting geolocation especially accurately, sacrificing device energy and time;
  • maximumAge β€” sets the time after which cached geolocation should be updated;
  • timeout β€” sets the time interval for updating geolocation.

Observe dynamically

If getCurrentPosition allows knowing the geolocation once, then to observe the constantly changing location, it is better to use the watchPosition method:

        
          
          navigator.geolocation.watchPosition(position => {  const { latitude, longitude } = position.coords})// Continuously overwrite latitude and longitude// the user's coordinates
          navigator.geolocation.watchPosition(position => {
  const { latitude, longitude } = position.coords
})

// Continuously overwrite latitude and longitude
// the user's coordinates

        
        
          
        
      

The watchPosition method endlessly calls the callback so that the data doesn't stagnate.

Stop observation

The watchPosition method returns the id of the current observation. It can be used in the clearWatch method to stop the observation:

        
          
          const geoId = navigator.geolocation.watchPosition(position => {  // Observing geolocation and storing the id in geoId})function geoWatchStopper() {  navigator.geolocation.clearWatch(geoId)  // Stop observation}
          const geoId = navigator.geolocation.watchPosition(position => {
  // Observing geolocation and storing the id in geoId
})

function geoWatchStopper() {
  navigator.geolocation.clearWatch(geoId)
  // Stop observation
}

        
        
          
        
      

How to handle errors

In the getCurrentPosition and watchPosition methods, a callback can be passed for handling errors. They are handled by the GeolocationPositionError object, which can be conveniently handled using the switch:

        
          
          function handleError(error) {  // This function can be passed as a callback in case of errors  const { code } = error  switch (code) {    case GeolocationPositionError.TIMEOUT:      // The time to obtain geolocation has expired      break    case GeolocationPositionError.PERMISSION_DENIED:      // The user has denied tracking their geolocation      break    case GeolocationPositionError.POSITION_UNAVAILABLE:      // Unable to obtain the location      break  }}
          function handleError(error) {
  // This function can be passed as a callback in case of errors

  const { code } = error

  switch (code) {
    case GeolocationPositionError.TIMEOUT:
      // The time to obtain geolocation has expired
      break
    case GeolocationPositionError.PERMISSION_DENIED:
      // The user has denied tracking their geolocation
      break
    case GeolocationPositionError.POSITION_UNAVAILABLE:
      // Unable to obtain the location
      break
  }
}

        
        
          
        
      

In practice

Advice 1

πŸ›  Using the Geolocation API, you can obtain the user's coordinates and then find a location on the map based on them. To do this, we will create a small function that will assemble a link with longitude and latitude, and then we will insert it into an iframe with the map:

        
          
          // On button click, we look for the locationbutton.addEventListener('click', findLocation)function findLocation() {  if (!navigator.geolocation) {    status.textContent = 'Your browser does not support geolocation...'  } else {    navigator.geolocation.getCurrentPosition(success, error)  }  // If everything is good, we assemble the link  function success(position) {    const { longitude, latitude }  = position.coords    map.src = `https://www.openstreetmap.org/export/embed.html?bbox=${longitude}%2C${latitude}&layer=mapnik`  }  // If something goes wrong, we simply write about it  function error() {    status.textContent = 'Unable to determine your geolocation :('  }}
          // On button click, we look for the location
button.addEventListener('click', findLocation)

function findLocation() {
  if (!navigator.geolocation) {
    status.textContent = 'Your browser does not support geolocation...'
  } else {
    navigator.geolocation.getCurrentPosition(success, error)
  }

  // If everything is good, we assemble the link
  function success(position) {
    const { longitude, latitude }  = position.coords

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

  // If something goes wrong, we simply write about it
  function error() {
    status.textContent = 'Unable to determine your geolocation :('
  }
}

        
        
          
        
      

If you click the button, the map will zoom in on your location:

Open demo in the new window

πŸ›  It's convenient to check at the very beginning whether we have the ability to work with geolocation. For this, in our findLocation function, we have the following construct:

        
          
          if (!navigator.geolocation) {  status.textContent = 'Your browser does not support geolocation...'} else {  navigator.geolocation.getCurrentPosition(success, error)}
          if (!navigator.geolocation) {
  status.textContent = 'Your browser does not support geolocation...'
} else {
  navigator.geolocation.getCurrentPosition(success, error)
}

        
        
          
        
      

navigator.geolocation takes values of type boolean, so if geolocation cannot be used, we can immediately inform about it. But if everything is fine, we just need to request geolocation and pass it to the callbacks πŸ™‚