I'm currently working on implementing live navigation functionality in a web application using JavaScript. The goal is to update a tracker marker on a map according to the user's position on a predefined route. However, I've encountered an issue with updating the currentPositionIndex variable within the watchPosition callback function.
Here's a brief overview of the problem:
The application starts by setting up a watch for the user's position using navigator.geolocation.watchPosition. Inside the watchPosition callback, I'm attempting to update the currentPositionIndex variable based on the user's position along the route. However, it seems that the currentPositionIndex variable doesn't update as expected inside the callback. As a result, the tracker marker on the map doesn't move along the route after the user reaches the first coordinate. I suspect that the issue might be related to the asynchronous nature of the watchPosition function and how it interacts with the closure around the callback function. Despite trying various approaches, I haven't been able to resolve the problem.
liveNavigation(route) {
let currentPositionIndex = 0;
console.log(route);
const updatePosition = () => {
// Check if geolocation is available in the browser
if (navigator.geolocation) {
//let currentPositionIndex = 0;
// Start watching the user's position with higher accuracy
const watchId = navigator.geolocation.watchPosition((position) => {
const userCoordinates = [position.coords.latitude, position.coords.longitude];
// Extract coordinates from the route
const routeCoordinates = route.coordinates;
console.log(routeCoordinates);
document.querySelector("#lat").innerText = userCoordinates[0];
document.querySelector("#long").innerText= userCoordinates[1];
const currentPosition = routeCoordinates[currentPositionIndex];
const distance = L.latLng(userCoordinates).distanceTo(currentPosition);
console.log(distance);
document.getElementById("address").value = distance;
document.querySelector("#routeIndex").innerText = currentPositionIndex;
document.querySelector("#distanceFromRoute").innerText= distance;
// Create the tracker marker with a different icon
this.trackerMarker = L.marker(routeCoordinates[0], { icon: Map.getIcon() }).addTo(this.map);
if (distance < 10) {
// Move the tracker marker to the current position
this.trackerMarker.setLatLng(currentPosition);
document.querySelector("#distanceFromRoute").innerText = "Setting pos to route";
// Calculate the bearing between current and next positions
if (currentPositionIndex < route.coordinates.length - 1) {
const nextPosition = route.coordinates[currentPositionIndex + 1];
const bearing = this.getBearing(currentPosition, nextPosition);
// Rotate the tracker marker icon based on the calculated bearing
this.trackerMarker.setRotationAngle(bearing);
}
if (currentPositionIndex === route.coordinates.length - 1) {
console.log('Navigation completed.');
navigator.geolocation.clearWatch(watchId); // Stop watching position
return;
}
document.querySelector("#routeIndex").innerText = currentPositionIndex;
document.querySelector("#distanceFromRoute").innerText= distance;
currentPositionIndex++;
} else {
// Handle deviation
this.checkRouteDeviation(route);
}
}, (error) => {
console.error('Error getting user location:', error.message);
}, { enableHighAccuracy: true, maximumAge: 0, timeout: 5000 }); // Configure options for high accuracy
} else {
console.error('Geolocation is not supported by this browser.');
}
};
// Start live navigation
updatePosition();
}