Geolocation API
The Geolocation API allows a website to get the user's geographic location (latitude, longitude) with the user's permission. It is very useful for features such as campus attendance, finding the nearest location, or tracking.
Code Example
Basics — getCurrentPosition
// Request the user's location
navigator.geolocation.getCurrentPosition(
function (position) {
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
console.log('Akurasi:', position.coords.accuracy, 'meter');
console.log('Timestamp:', new Date(position.timestamp));
},
function (error) {
console.error('Error:', error.message);
switch (error.code) {
case error.PERMISSION_DENIED:
console.error('Excused location ditolak');
break;
case error.POSITION_UNAVAILABLE:
console.error('Location unavailable');
break;
case error.TIMEOUT:
console.error('Request timeout');
break;
}
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 300000
}
);
watchPosition — Monitor Location Changes
// Monitor the location continuously
const watchId = navigator.geolocation.watchPosition(
function (position) {
console.log('New position:');
console.log('Lat:', position.coords.latitude);
console.log('Lng:', position.coords.longitude);
updateMap(position.coords.latitude, position.coords.longitude);
},
function (error) {
console.error('Error tracking:', error);
},
{
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 10000
}
);
// Stop the watch when it is no longer needed
// For example when the user leaves the tracking page
navigator.geolocation.clearWatch(watchId);
Code Explanation
PositionOptions
{
enableHighAccuracy: true, // GPS (more accurate but slower)
timeout: 10000, // maximum wait time (ms)
maximumAge: 300000 // use a cached location for up to 5 minutes
}
Position Object
position.coords.latitude // latitude (-90 to 90)
position.coords.longitude // longitude (-180 to 180)
position.coords.accuracy // accuracy in meters
position.coords.altitude // altitude in meters (if available)
position.coords.speed // speed in m/s (if available)
position.coords.heading // direction in degrees (if available)
position.timestamp // time the location was obtained (ms)
Error Handling
function getLocation() {
return new Promise((resolve, reject) => {
if (!navigator.geolocation) {
reject(new Error('Geolocation is not supported by this browser'));
return;
}
navigator.geolocation.getCurrentPosition(
position => resolve(position.coords),
error => {
switch (error.code) {
case error.PERMISSION_DENIED:
reject(new Error('Location permission denied. Enable it in your browser settings.'));
break;
case error.POSITION_UNAVAILABLE:
reject(new Error('Location unavailable. Make sure GPS is enabled.'));
break;
case error.TIMEOUT:
reject(new Error('Request location timeout. Try again.'));
break;
default:
reject(new Error('An error occurred while getting location.'));
}
},
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 300000 }
);
});
}
Real-World Examples
Campus Attendance with Geolocation
class CampusAttendance {
constructor(campusLat, campusLng, radiusMeter = 100) {
this.campusLat = campusLat;
this.campusLng = campusLng;
this.radius = radiusMeter;
}
// Calculate the distance between two points (Haversine formula)
calculateDistance(lat1, lng1, lat2, lng2) {
const R = 6371e3; // Earth's radius in meters
const phi1 = (lat1 * Math.PI) / 180;
const phi2 = (lat2 * Math.PI) / 180;
const deltaPhi = ((lat2 - lat1) * Math.PI) / 180;
const deltaLambda = ((lng2 - lng1) * Math.PI) / 180;
const a =
Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +
Math.cos(phi1) * Math.cos(phi2) *
Math.sin(deltaLambda / 2) * Math.sin(deltaLambda / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // distance in meters
}
// Check whether the user is inside the campus area
async checkLocation() {
const coords = await getLocation();
const distance = this.calculateDistance(
coords.latitude, coords.longitude,
this.campusLat, this.campusLng
);
return {
inArea: distance <= this.radius,
distance: Math.round(distance),
latitude: coords.latitude,
longitude: coords.longitude
};
}
// Check in
async attendance() {
try {
const location = await this.checkLocation();
if (!location.inArea) {
throw new Error(
`You are ${location.distance}m from the university. ` +
`Must be within a ${this.radius}m radius.`
);
}
// Send the attendance data to the server
const response = await fetch('/api/attendance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
latitude: location.latitude,
longitude: location.longitude,
timestamp: new Date().toISOString(),
radius: this.radius
})
});
if (!response.ok) throw new Error('Failed to save attendance');
return { success: true, message: 'Attendance successful!' };
} catch (error) {
return { success: false, message: error.message };
}
}
}
// Usage
// Campus coordinates: New York (-6.8912, 107.6108), radius 100m
const attendance = new CampusAttendance(-6.8912, 107.6108, 100);
document.querySelector('#btn-attendance').addEventListener('click', async function () {
this.disabled = true;
this.textContent = 'Memprocess...';
const result = await attendance.attendance();
if (result.success) {
showNotification(result.message, 'success');
} else {
showNotification(result.message, 'error');
}
this.disabled = false;
this.textContent = 'Check In Now';
});
Real-Time Location Tracking
class LocationTracker {
constructor() {
this.watchId = null;
this.isTracking = false;
this.locations = [];
}
start(callback) {
if (this.isTracking) return;
this.watchId = navigator.geolocation.watchPosition(
position => {
const data = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy,
timestamp: new Date(position.timestamp)
};
this.locations.push(data);
callback(data);
},
error => {
console.error('Tracking error:', error);
this.stop();
},
{ enableHighAccuracy: true, maximumAge: 5000 }
);
this.isTracking = true;
}
stop() {
if (this.watchId !== null) {
navigator.geolocation.clearWatch(this.watchId);
this.watchId = null;
}
this.isTracking = false;
return this.locations;
}
getHistory() {
return [...this.locations];
}
clearHistory() {
this.locations = [];
}
}
// Usage
const tracker = new LocationTracker();
document.querySelector('#btn-start-tracking').addEventListener('click', function () {
tracker.start(data => {
updateMap(data.latitude, data.longitude);
addLogEntry(data);
});
this.textContent = 'Tracking active...';
});
document.querySelector('#btn-stop-tracking').addEventListener('click', function () {
const locations = tracker.stop();
console.log('Locations recorded:', locations.length, 'points');
saveRoute(locations);
});
Finding the Nearest Location from Coordinates
const campusLocation = [
{ name: 'Building A (Rektorat)', lat: -6.8912, lng: 107.6108 },
{ name: 'Building B (Teknik)', lat: -6.8915, lng: 107.6112 },
{ name: 'Library', lat: -6.8910, lng: 107.6105 },
{ name: 'Kantin', lat: -6.8918, lng: 107.6115 }
];
async function findNearestLocation() {
try {
const coords = await getLocation();
const withDistance = campusLocation.map(loc => ({
...loc,
distance: calculateDistance(coords.latitude, coords.longitude, loc.lat, loc.lng)
}));
withDistance.sort((a, b) => a.distance - b.distance);
console.log('Nearest location:', withDistance[0].name);
console.log('Distance:', Math.round(withDistance[0].distance), 'meter');
return withDistance[0];
} catch (error) {
console.error('Failed to get location:', error);
}
}
Tips and Notes
// 1. Always check whether geolocation is supported
if ('geolocation' in navigator) {
// Browser supports it
} else {
console.error('Browser does not support geolocation');
}
// 2. HTTPS is required for geolocation in production
// HTTP only works on localhost for development
// 3. Request permission explicitly
// The browser will show the permission dialog automatically
// Don't call getCurrentPosition too often
// 4. handleHighAccuracy: true uses GPS (more accurate, but)
// it consumes more battery and is slower
// 5. Clean up watchPosition when the component is destroyed
window.addEventListener('beforeunload', function () {
if (tracker && tracker.isTracking) {
tracker.stop();
}
});
Conclusion
The Geolocation API allows a website to get the user's location with permission. Use getCurrentPosition to get the location once, and watchPosition for real-time tracking. Always handle errors (permission denied, timeout), validate distance for features like campus attendance, and clean up watchPosition when it is no longer needed. Make sure to use HTTPS in production.