This is the documentation of version 0.64.0. Go to the latest version, 1.0.0-rc.5.

Routing module

The Routing module draws the routes calculateRoute returns, their waypoints, guidance, traffic along the way, and the route-related interactions.

What this module owns: the route lines, waypoints, section overlays, instruction arrows and summary bubbles it draws, and how they look (Route styling). It never restyles the roads underneath, which belong to the Styling Foundations module. Two looks reach it from outside:

No other knob reaches route layers — Who owns what.

Two features of the module have a guide of their own:

Guide Covers
Route styling Colour, width, waypoint size, layers, the knob catalogue, layer positioning and charging stop icons
Route sections The overlays drawn per stretch of road: tunnels, ferries, traffic, speed limit signs, border crossings and the rest

Initialization

import { TomTomMap, RoutingModule } from '@tomtom-org/maps-sdk/map';

const map = new TomTomMap({ mapLibre: { container: 'map' } });

const routingModule = await RoutingModule.create(map, {
    displayUnits: { distance: { type: 'metric' } }, // optional
    waypoints: { entryPoints: 'main-when-available' } // optional
});

Displaying routes

import { calculateRoute } from '@tomtom-org/maps-sdk/services';

const locations = [
    [4.9041, 52.3676], // Amsterdam
    [4.4777, 51.9244]  // Rotterdam
];
const routes = await calculateRoute({ locations });

await routingModule.showRoutes(routes);
await routingModule.showWaypoints(locations); // showRoutes draws no pins

showRoutes draws the route line only; the start, stop and destination pins are showWaypoints's. What locations takes is in Locations, every other request option in Route planning parameters.

Displaying guidance on map

A route calculated with guidance: { type: 'coded' } draws its instruction lines and arrows with no extra configuration:

const route = await calculateRoute({ locations, guidance: { type: 'coded' } });
await routingModule.showRoutes(route);

Route selection

With alternatives, one route is drawn as selected — the first unless told otherwise:

const routes = await calculateRoute({ locations, maxAlternatives: 2 });

await routingModule.showRoutes(routes, { selectedIndex: 1 });
await routingModule.selectRoute(0); // re-marks the shown routes, no recalculation

Waypoints

showWaypoints draws the pins, and clearWaypoints removes them; neither touches the routes, and clearRoutes leaves the pins.

A stop's pin is labelled with its name and, when the stop carries a pauseDurationSeconds, how long the route waits there, in the SDK's display units:

const locations = [
    [2.1734, 41.3851],
    {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [2.4467, 41.5381] },
        properties: { pauseDurationSeconds: 30 * 60 } // the pin reads "30 min" under the stop name
    },
    [2.8214, 41.9794]
];

await routingModule.showRoutes(await calculateRoute({ locations }));
await routingModule.showWaypoints(locations);

Charging stop pins carry the same label: the whole time spent there, charging plus any wait asked for at the same place. A label that wants only the charging part reads chargingDuration:

const routingModule = await RoutingModule.create(map, {
    chargingStops: { label: { title: ['format', ['get', 'chargingDuration'], {}] } }
});

Waypoints or places

places.events.on('click', async (place) => {
    const locations = [origin, place, destination];
    await places.clear();
    await routingModule.showRoutes(await calculateRoute({ locations }));
    await routingModule.showWaypoints(locations);
});

A location several routing modules share, such as the one destination of routes from several origins, can be marked once by a Places module instead.

Everything below reaches the waypoints already shown when it changes through applyConfig, and they keep their ids and event states. It is all live on the waypoints playground:

Pins per role

waypoints.icon.style styles every pin; waypoints.icon.start, middle and finish style one role each, over it. A pin left without a fillColor takes the route's color:

const routingModule = await RoutingModule.create(map, {
    waypoints: {
        icon: {
            style: { outlineColor: '#FFFFFF' },
            start: { style: { fillColor: '#1B7A3E' } },
            finish: { style: { fillColor: '#C0392B' } }
        }
    }
});

Stop marks

Labels

Each pin is labelled with its POI name, else its address, and its wait. waypoints.label.visible: false drops the labels, and waypoints.label.title writes your own, as label.title does for places — a function of the waypoint, or a MapLibre expression:

import { buildWaypointTitle } from '@tomtom-org/maps-sdk/map';

routingModule.applyConfig({
    waypoints: {
        label: {
            title: (waypoint) => (waypoint.properties.indexType === 'finish' ? 'Home' : buildWaypointTitle(waypoint) ?? '')
        }
    }
});

The label's colour, halo and size are in Route styling.

Hover and click

Once a handler covers the waypoints, a hovered or clicked pin grows by waypoints.highlight.sizeFactor, its stop mark with it: 1.2 times unless set, clamped to 1 to 1.5, and 1 draws it as any other. The waypoints scope has the event state methods to put that state from your own UI:

routingModule.events.waypoints.on('hover', (waypoint) => showStopCard(waypoint.properties));
routingModule.events.waypoints.setEventState({ index: 1, state: 'click' });

Icons of your own

A role's image replaces its pin, and waypoints.icon.mapping picks a pin per waypoint from its data, as icon.mapping does for places:

const routingModule = await RoutingModule.create(map, {
    waypoints: {
        icon: {
            finish: { image: { image: chequeredFlagSVG } },
            mapping: { to: 'poiCategory', fn: (waypoint) => waypoint.properties.poi?.categories?.[0] }
        }
    }
});

Showing and hiding

setVisible(false) hides everything the module draws — route lines, waypoints, sections, guidance, charging stops, summary bubbles and border crossings — and keeps what it shows:

const routingModule = await RoutingModule.create(map, { visible: false }); // starts hidden
await routingModule.showRoutes(route);   // kept, not drawn
routingModule.setVisible(true);          // draws the route
routingModule.isVisible();               // true

Events

Each part of a route has a scope of its own, on the user events surface:

routingModule.events.mainLines.on('click', (route, lngLat) => console.log(route.properties));
routingModule.events.waypoints.on('click', (waypoint) => console.log(waypoint.properties.indexType));
routingModule.events.incidents.on('hover', (section) => console.log(section.properties.delayInSeconds));
routingModule.events.instructionLines.on('click', (instruction) => console.log(instruction.properties));
routingModule.events.summaryBubbles.on('click', (summary) => console.log(summary.properties));
routingModule.events.chargingStops.on('click', (stop) => console.log(stop.properties));

// Removes every click handler of the scope; `on` returns an unsubscribe for one handler
routingModule.events.mainLines.off('click');

A hovered or clicked route draws its outline wider, selected or not, once a handler covers the routes. The module's event state methods act on the routes, and each named scope has them for its own features. A click marks the route; selectRoute makes it the selected one:

routingModule.events.mainLines.on('click', (route) => routingModule.selectRoute(route.properties.index));

routingModule.setEventState({ index: 1, state: 'hover' });
const { click: [clickedRouteID] = [] } = routingModule.getEventStates();

highlight.outline.widthFactor sets how much wider: 1.2 times unless set, clamped to 1 to 1.25 so the outline never covers a section halo beneath the route, and 1 draws a hovered route as any other. An outline width given through layers.mainLines.routeOutline is drawn as given, in every state.

routingModule.applyConfig({ highlight: { outline: { widthFactor: 1.25 } } });

Multiple module instances

Each instance has its own sources, layers, configuration and events, for comparing route types or showing routes for several users:

const carRoutes = await RoutingModule.create(map, { color: '#2ECC71' });
const truckRoutes = await RoutingModule.create(map, { color: '#E67E22' });

await carRoutes.showRoutes(carRoute);
await truckRoutes.showRoutes(truckRoute);

Reading shown data

getShown() returns what the module draws, as prepared for display, split by what draws it:

const shown = routingModule.getShown();
if (shown.mainLines.features.length > 0) {
    console.log(`Showing ${shown.mainLines.features.length} routes, ${shown.waypoints.features.length} waypoints`);
}

Its entries: mainLines, waypoints, incidents, ferries, chargingStops, tollRoads, tunnels, vehicleRestricted, instructionLines, instructionArrows, summaryBubbles and countryCrossings, plus one <type>Sections per generated section type — urbanSections, motorwaySections and the rest.

API reference

RoutingModule and RoutingModuleConfig.

Related guides and examples

Services integration

Related examples

Related map modules