← thecodex.expert · The Codex Family of Knowledge
The Codex / JavaScript / Geolocation

Geolocation

Getting the user's location — getCurrentPosition, watchPosition, permissions, accuracy, and handling errors.

What it is, in plain English: The Geolocation API lets a web page request the user's physical location. The browser asks the user for permission first — you cannot get location silently. getCurrentPosition() gets the location once. watchPosition() tracks the location continuously (for navigation apps). Location data includes latitude, longitude, accuracy, altitude, speed, and heading.
Where this bites you

coords.speed (like heading, altitude and altitudeAccuracy) is null when the device can't measure them, which is usual on laptops and on Wi-Fi-based fixes. JavaScript happily calculates null * 3.6 as 0, so a speed display shows a confident 0.0 km/h instead of admitting it doesn't know.

// <span id="speed"></span>
const speedDisplay = document.getElementById("speed");

navigator.geolocation.getCurrentPosition((position) => {
  speedDisplay.textContent = `${(position.coords.speed * 3.6).toFixed(1)} km/h`;
  console.log(position.coords.speed, speedDisplay.textContent);
});
// null "0.0 km/h"

Getting the user's location

User permission required. The browser always asks before sharing location. You cannot get location without explicit user consent. Also requires HTTPS (or localhost for development).

getCurrentPosition — one-time location

navigator.geolocation.getCurrentPosition(
  // Success callback:
  (position) => {
    const { latitude, longitude, accuracy } = position.coords;
    console.log(`Lat: ${latitude}, Lng: ${longitude}`);
    console.log(`Accuracy: ±${accuracy} metres`);
    showOnMap(latitude, longitude);
  },

  // Error callback:
  (error) => {
    if (error.code === error.PERMISSION_DENIED) {
      showMessage("Please allow location access to use this feature");
    } else {
      showMessage("Could not get your location — try again");
    }
  },

  // Options:
  {
    enableHighAccuracy: true,   // use GPS if available (slower, uses more battery)
    timeout: 10000,             // give up after 10 seconds
    maximumAge: 0,              // don't use cached position (always fresh)
  }
);

watchPosition — continuous tracking

// For navigation — fires every time position changes:
const watchId = navigator.geolocation.watchPosition(
  (position) => {
    updateMapMarker(position.coords.latitude, position.coords.longitude);
    speedDisplay.textContent = `${(position.coords.speed * 3.6).toFixed(1)} km/h`;
  },
  (error) => console.error(error.message),
  { enableHighAccuracy: true }
);

// Stop tracking:
navigator.geolocation.clearWatch(watchId);

The watchPosition example above has exactly this line. Only latitude, longitude and accuracy are always numbers. Check every other field for null before you do arithmetic with it:

const speedDisplay = document.getElementById("speed");

navigator.geolocation.getCurrentPosition((position) => {
  const { speed } = position.coords;             // null when the device can't measure it
  speedDisplay.textContent = speed === null
    ? "speed unavailable"
    : `${(speed * 3.6).toFixed(1)} km/h`;
  console.log(speed, speedDisplay.textContent);
});
// null "speed unavailable"

Calculate distance between two coordinates

// Haversine formula — great-circle distance:
function getDistance(lat1, lng1, lat2, lng2) {
  const R    = 6371;  // Earth radius in km
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = Math.sin(dLat/2) ** 2 +
    Math.cos(lat1 * Math.PI/180) * Math.cos(lat2 * Math.PI/180) * Math.sin(dLng/2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

// Mumbai to Delhi:
console.log(getDistance(19.076, 72.878, 28.644, 77.216).toFixed(0), "km");  // 1151 km
Try It Yourself

Official Sources

The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.