Getting started with Navigation
The Navigation module provides comprehensive turn-by-turn navigation capabilities, enabling real-time guidance along calculated routes. It includes features such as voice instructions, automatic route recalculation, lane guidance, and speed limit warnings.
Starting navigation
To start navigation, you first need a calculated route:
import {
NavigationService,
NavigationInstruction,
NavigationInstructionUpdateEvents,
GemError,
Landmark,
Route,
TaskHandler,
} from '@magiclane/maps-sdk';
let navigationHandler: TaskHandler | null = null;
function startNavigation() {
const routesMap = map.preferences.routes;
if (!routesMap.mainRoute) {
console.log('No main route available');
return;
}
navigationHandler = NavigationService.startNavigation(routesMap.mainRoute, undefined, {
onNavigationInstruction: (
instruction: NavigationInstruction,
events: Set<NavigationInstructionUpdateEvents>
) => {
console.log('Next turn:', instruction.nextTurnInstruction);
console.log('Distance to next turn:', instruction.timeDistanceToNextTurn.totalDistanceM, 'm');
updateNavigationUI(instruction);
},
onTextToSpeechInstruction: (textInstruction: string) => {
// Use browser TTS or custom audio to speak the instruction
const utterance = new SpeechSynthesisUtterance(textInstruction);
speechSynthesis.speak(utterance);
},
onWaypointReached: (landmark: Landmark) => {
console.log('Reached waypoint:', landmark.name);
},
onDestinationReached: (landmark: Landmark) => {
console.log('Arrived at destination:', landmark.name);
stopNavigation();
},
onRouteUpdated: (route: Route) => {
console.log('Route was recalculated');
},
onError: (error: GemError) => {
console.error('Navigation error:', error);
stopNavigation();
},
});
map.startFollowingPosition();
}
Navigation events
The startNavigation and startSimulation methods accept an options object with multiple callback functions:
| Callback | Description |
|---|---|
onNavigationInstruction | Periodic updates (typically every second) with the current NavigationInstruction and a set of NavigationInstructionUpdateEvents |
onNavigationStarted | Called when navigation has started |
onTextToSpeechInstruction | Provides text strings meant for voice guidance (TTS) |
onWaypointReached | Called when an intermediate waypoint is reached |
onDestinationReached | Called when the final destination is reached |
onRouteUpdated | Called when the route is recalculated (e.g., after a deviation) |
onBetterRouteDetected | Called when a faster alternative route is detected |
onBetterRouteRejected | Called when a better route is rejected |
onError | Called when navigation fails with a GemError |
onNotifyStatusChange | Called when navigation status changes |
onRouteCalculationStarted | Called when route recalculation begins |
onRouteCalculationCompleted | Called when route recalculation completes |
Simulation mode
For testing navigation without actual GPS movement, use startSimulation:
import { NavigationService, Route, TaskHandler } from '@magiclane/maps-sdk';
let simulationHandler: TaskHandler | null = null;
function startSimulation(route: Route) {
simulationHandler = NavigationService.startSimulation(route, undefined, {
onNavigationInstruction: (instruction, events) => {
console.log('Simulated instruction:', instruction.nextTurnInstruction);
updateNavigationUI(instruction);
},
onDestinationReached: (landmark) => {
console.log('Simulation complete');
stopNavigation();
},
onError: (error) => {
console.error('Simulation error:', error);
},
});
map.startFollowingPosition();
}
The startSimulation method accepts the same callbacks as startNavigation. The second parameter is a deprecated callback — pass undefined for it.
Stopping navigation
When navigation is complete or cancelled:
function stopNavigation() {
if (navigationHandler) {
NavigationService.cancelNavigation(navigationHandler);
navigationHandler = null;
}
map.stopFollowingPosition();
console.log('Navigation stopped');
}
Navigation UI integration
Example of integrating navigation with a map view:
import {
GemMap,
NavigationService,
NavigationInstruction,
NavigationInstructionUpdateEvents,
GemAnimation,
AnimationType,
GemError,
Route,
TaskHandler,
} from '@magiclane/maps-sdk';
let navigationHandler: TaskHandler | null = null;
function setupNavigationUI(gemMap: GemMap, route: Route) {
navigationHandler = NavigationService.startNavigation(route, undefined, {
onNavigationInstruction: (
instruction: NavigationInstruction,
events: Set<NavigationInstructionUpdateEvents>
) => {
// Update instruction panel
const nextTurn = instruction.nextTurnInstruction;
const distanceToTurn = instruction.timeDistanceToNextTurn.totalDistanceM;
const remainingDistance = instruction.remainingTravelTimeDistance.totalDistanceM;
const remainingTime = instruction.remainingTravelTimeDistance.totalTimeS;
document.getElementById('instruction-text')!.textContent = nextTurn;
document.getElementById('instruction-distance')!.textContent = `${Math.round(distanceToTurn)}m`;
document.getElementById('distance-remaining')!.textContent =
`${(remainingDistance / 1000).toFixed(1)} km`;
document.getElementById('time-remaining')!.textContent =
`${Math.round(remainingTime / 60)} min`;
},
onTextToSpeechInstruction: (textInstruction: string) => {
const utterance = new SpeechSynthesisUtterance(textInstruction);
speechSynthesis.speak(utterance);
},
onDestinationReached: () => {
console.log('Arrived at destination!');
stopNavigation();
},
onError: (error: GemError) => {
console.error('Navigation error:', error);
stopNavigation();
},
});
// Follow user position
gemMap.startFollowingPosition({
animation: new GemAnimation({ type: AnimationType.linear, duration: 1000 }),
});
}
function stopNavigation() {
if (navigationHandler) {
NavigationService.cancelNavigation(navigationHandler);
navigationHandler = null;
}
}
Next Steps
Now that you understand navigation basics, you can explore:
- Voice guidance configuration
- Better route detection and alternatives
- Roadblocks management