Skip to main content

Navigate Route

|

In this guide, you will learn how to compute a route between a departure point and a destination point, render the route on an interactive map, and then navigate along the route with real GPS positioning.

How it works

This example demonstrates the following features:

  • Compute routes between current location and destination
  • Display routes on a map with alternative route options
  • Begin turn-by-turn navigation with real-time positioning
  • Show navigation instructions and remaining distance/time
  • Handle route recalculation when off-route

Live Demo

Try the interactive demo below. Click "Build Route" and then "Start Navigation" to begin turn-by-turn guidance:

Code Implementation

Building the Route

Calculate route from current location to destination:

index.ts
function onBuildRouteButtonPressed() {
if (!currentLocation) {
showMessage('Current location is needed to compute the route.');
return;
}
const departureLandmark = Landmark.withCoordinates(currentLocation);
const destinationLandmark = Landmark.withLatLng({ latitude: 52.51614, longitude: 13.37748 });
const routePreferences = new RoutePreferences({});
showMessage('The route is calculating.');

routingHandler = RoutingService.calculateRoute(
[departureLandmark, destinationLandmark],
routePreferences,
(err: GemError, calculatedRoutes: Route[]) => {
routingHandler = null;
if (err === GemError.routeTooLong) {
showMessage('The destination is too far from your current location. Change the coordinates of the destination.');
return;
}
if (err === GemError.success) {
const routesMap = map?.preferences.routes;
calculatedRoutes.forEach((route, index) => {
const label = getRouteLabel(route);
routesMap?.add(route, index === 0, { label });
});
map?.centerOnRoutes({ routes: calculatedRoutes });
showMessage('Route calculated successfully!');
routes = calculatedRoutes;
areRoutesBuilt = true;
} else {
showMessage('Route calculation failed.');
}
updateUI();
}
);
updateUI();
}

Starting Navigation

Begin turn-by-turn navigation along the calculated route:

index.ts
function onStartNavigation() {
if (!map) return;
const routesMap = map.preferences.routes;
if (!routesMap.mainRoute) {
showMessage('No main route available');
return;
}
navigationHandler = NavigationService.startSimulation(
routesMap.mainRoute,
undefined,
{
onNavigationInstruction: (instruction: NavigationInstruction, events: any) => {
isNavigationActive = true;
currentInstruction = instruction;
updateUI();
},
onError: (error: GemError) => {
isNavigationActive = false;
cancelRoute();
if (error !== GemError.cancel) stopNavigation();
updateUI();
}
}
);
map.startFollowingPosition();
updateUI();
}

// --- Stop navigation ---
function stopNavigation() {
if (navigationHandler) {
NavigationService.cancelNavigation(navigationHandler);
navigationHandler = null;
}
cancelRoute();
isNavigationActive = false;
updateUI();
}

Handling Navigation Updates

Process navigation instructions and update the UI:

index.ts
function onNavigationUpdate(instruction: NavigationInstruction) {
currentInstruction = instruction;

// Update instruction panel
if (instruction.text) {
showInstructionPanel(instruction);
}

// Update bottom info panel
showBottomPanel(instruction);

// Update current location
if (instruction.currentPosition) {
currentLocation = instruction.currentPosition;
}
}

function showInstructionPanel(instruction: NavigationInstruction) {
let panel = document.getElementById('nav-instruction-panel');

if (!panel) {
panel = document.createElement('div');
panel.id = 'nav-instruction-panel';
panel.style.cssText = `
position: fixed; top: 80px; left: 50%; transform: translateX(-50%);
background: white; padding: 20px 30px; border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 2000; min-width: 350px; text-align: center;
`;
document.body.appendChild(panel);
}

const distanceToTurn = getFormattedDistanceToNextTurn(instruction);

panel.innerHTML = `
<div style="display: flex; align-items: center; gap: 16px;">
<div style="font-size: 2em;">${getManeuverIcon(instruction.type)}</div>
<div style="flex: 1; text-align: left;">
<div style="font-size: 1.2em; font-weight: 600; margin-bottom: 4px;">
${instruction.text}
</div>
<div style="color: #666; font-size: 1em;">
in ${distanceToTurn}
</div>
</div>
</div>
`;
}

function showBottomPanel(instruction: NavigationInstruction) {
let panel = document.getElementById('nav-bottom-panel');

if (!panel) {
panel = document.createElement('div');
panel.id = 'nav-bottom-panel';
panel.style.cssText = `
position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
background: white; padding: 16px 24px; border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 2000; display: flex; gap: 32px;
`;
document.body.appendChild(panel);
}

const distance = getFormattedRemainingDistance(instruction);
const duration = getFormattedRemainingDuration(instruction);
const eta = getFormattedETA(instruction);

panel.innerHTML = `
<div>
<div style="color: #666; font-size: 0.85em; margin-bottom: 4px;">Distance</div>
<div style="font-weight: 600; font-size: 1.2em;">${distance}</div>
</div>
<div>
<div style="color: #666; font-size: 0.85em; margin-bottom: 4px;">Duration</div>
<div style="font-weight: 600; font-size: 1.2em;">${duration}</div>
</div>
<div>
<div style="color: #666; font-size: 0.85em; margin-bottom: 4px;">Arrival</div>
<div style="font-weight: 600; font-size: 1.2em;">${eta}</div>
</div>
`;
}

function getManeuverIcon(type: string): string {
// Return appropriate icon based on maneuver type
const icons = {
'turn-left': '⬅️',
'turn-right': '➡️',
'turn-slight-left': '↖️',
'turn-slight-right': '↗️',
'turn-sharp-left': '↩️',
'turn-sharp-right': '↪️',
'straight': '⬆️',
'roundabout': '🔄',
'destination': '🏁'
};

return icons[type] || '⬆️';
}

Key Features

  • Real GPS Navigation: Uses actual device location for navigation
  • Turn-by-Turn Instructions: Clear visual and text guidance
  • Live Updates: Distance, duration, and ETA update in real-time
  • Follow Mode: Map automatically follows current position
  • Maneuver Icons: Visual indicators for upcoming turns
  • Route Recalculation: Automatic rerouting when deviating from path

Next Steps