Building a Location-Aware Trip Meter
The Geolocation API gives web applications a standardized way to request a user's position and receive updates as they move. Because the underlying location source — whether GPS, Wi-Fi positioning, or manual entry — is abstracted away, the same code works across devices. Location lookups take time, so all requests are asynchronous and use callbacks.
This project builds a simple trip meter that records the user's starting position on page load and continuously displays the distance traveled since then.
Compatibility Check
Before using the API, verify the browser supports it by checking for the geolocation object:
// check for Geolocation support
if (navigator.geolocation) {
console.log('Geolocation is supported!');
}
else {
console.log('Geolocation is not supported for this Browser/OS version yet.');
}
Setting Up the Page
The trip meter requires a few empty spans that will be populated with location data and distance calculations:
<div id="tripmeter">
<p>
Starting Location (lat, lon):<br/>
<span id="startLat">???</span>°, <span id="startLon">???</span>°
</p>
<p>
Current Location (lat, lon):<br/>
<span id="currentLat">???</span>°, <span id="currentLon">???</span>°
</p>
<p>
Distance from starting location:<br/>
<span id="distance">0</span> km
</p>
</div>
Getting the Initial Position
When the page loads, call getCurrentPosition() to fetch the starting location. This method takes a success callback that receives a position object. The coordinates are stored for later use and displayed in the corresponding spans:
window.onload = function() {
var startPos;
navigator.geolocation.getCurrentPosition(function(position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
});
};
On the first request, the browser typically prompts the user for permission. Subsequent requests may bypass this prompt if the user has set a persistent preference. Beyond latitude and longitude, the position object can include additional data like altitude or heading depending on the location source.
Handling Location Errors
Location lookups can fail for various reasons — a GPS signal might be unavailable, or the user may have revoked permission. Pass an error callback as the second argument to getCurrentPosition() to handle these cases and inform the user:
window.onload = function() {
var startPos;
navigator.geolocation.getCurrentPosition(function(position) {
// same as above
}, function(error) {
alert('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from locaton provider)
// 3: timed out
});
};
Tracking Movement
The initial call to getCurrentPosition() runs only once. To stay informed as the user moves, use watchPosition(), which fires its callback whenever the position changes:
navigator.geolocation.watchPosition(function(position) {
document.getElementById('currentLat').innerHTML = position.coords.latitude;
document.getElementById('currentLon').innerHTML = position.coords.longitude;
});
Calculating Distance
Inside the watchPosition() handler, add logic to compute the distance from the starting point:
navigator.geolocation.watchPosition(function(position) {
// same as above
document.getElementById('distance').innerHTML =
calculateDistance(startPos.coords.latitude, startPos.coords.longitude,
position.coords.latitude, position.coords.longitude);
});
The calculateDistance() function uses a geometric formula to find the distance between two coordinate pairs. This JavaScript implementation is adapted from a script by Moveable Type, released under a Creative Commons license:
function calculateDistance(lat1, lon1, lat2, lon2) {
var R = 6371; // km
var dLat = (lat2 - lat1).toRad();
var dLon = (lon2 - lon1).toRad();
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
}
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}



