Routing module
The Routing module draws the routes calculateRoute returns, with their
waypoints, guidance and traffic along the way, and handles their interactions.
The 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. Three looks reach it from outside:
- A route without a
colortakes the map’s accent. - Its traffic sections follow the Traffic Incidents module’s
colors.*knobs (Borrowed looks). - Its summary bubbles take the map’s
labelHaloandlabelcolours once a theme sets them.
No other knob reaches route layers. See Who owns what.
The code below geocodes four stops, calculates the route through them and draws both. The response goes to showRoutes unchanged. Change an address to re-plan it:
Two features of the module have a guide of their own:
| Guide | Covers |
|---|---|
| Route styling | Colour, width, waypoint size, layers, the knob catalogue and layer positioning |
| 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});- Without
displayUnits, the labels use the global units (TomTomConfig.instance.put({ displayUnits })) in force when they are drawn. Shown routes pick up a change on their nextshowRoutesor configuration change. getConfig()returns only what you passed, never the global units.
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 pinsshowRoutes draws the lines, sections, guidance and summary bubbles, but no pins.
showWaypoints draws the start, stop and destination pins.
Locations describes what locations takes.
Route planning parameters covers every other request option.
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, the module draws one route as selected, the first by default:
const routes = await calculateRoute({ locations, maxAlternatives: 2 });
await routingModule.showRoutes(routes, { selectedIndex: 1 });await routingModule.selectRoute(0); // re-marks the shown routes, no recalculationWaypoints
showWaypoints draws the pins, and clearWaypoints removes them. Neither touches the routes, and
clearRoutes leaves the pins.
A stop’s pin shows its name. If the stop has a pauseDurationSeconds, the pin also shows 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);The origin’s pin shows its wait too, though the routing service never gets an origin’s wait.
Waypoints or places
- A waypoint is any location a route is calculated through.
showWaypointsdraws it with its role (start, stop or finish), its stop mark and the module’swaypointsevents. - A place the user is still choosing among, such as a search result or a candidate stop, belongs to the
Places module. Once it joins the route, clear it there and pass it to
showWaypoints, so no location is drawn twice:
places.events.on('click', async (place) => { const locations = [origin, place, destination]; await places.clear(); await routingModule.showRoutes(await calculateRoute({ locations })); await routingModule.showWaypoints(locations);});If several routing modules share a location, such as the one destination of routes from several origins, you can mark it once with a Places module instead.
When you change any setting below through applyConfig, the waypoints already shown update and keep their
ids and event states. Try it all on the waypoints playground:
Pins per role
waypoints.icon.style styles every pin. waypoints.icon.start, middle and finish each style one role on
top of it. A pin 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
- A stop’s pin carries its number among the stops, starting at 1.
waypoints.stopNumberingcan also be'letters'(A to Z, then AA) or'none'. - The count includes stops that a mapping draws its own icon for, so the marks keep
matching the stop order. Those icons and a
middle.imagecarry no mark. - The start and finish pins draw their own glyph instead.
- The mark is the waypoint’s
stopDisplayLabelproperty, whichevents.waypointshandlers receive.
Labels
Each pin’s label shows its POI name, otherwise its address, and its wait. waypoints.label.visible: false drops
the labels. To write your own, set waypoints.label.title to a function of the waypoint or a
MapLibre expression, like label.title for places:
import { buildWaypointTitle } from '@tomtom-org/maps-sdk/map';
routingModule.applyConfig({ waypoints: { label: { title: (waypoint) => (waypoint.properties.indexType === 'finish' ? 'Home' : buildWaypointTitle(waypoint) ?? '') } }});Route styling covers the label’s colour, halo and size.
Hover and click
Once a handler covers the waypoints, a hovered or clicked pin and its stop mark grow by
waypoints.highlight.sizeFactor. It defaults to 1.2 and is clamped to 1 to 1.5, and 1 draws the pin like any
other. The waypoints scope has the event state methods to set that state from your
own UI:
routingModule.events.waypoints.on('hover', (waypoint) => showStopCard(waypoint.properties));routingModule.events.waypoints.setEventState({ index: 1, state: 'click' });A waypoint keeps the id you give it, a string or a number, and gets a generated string otherwise. The handlers,
setEventState and getEventStates carry that same id, so a waypoint with the id 5 is 5 in all of them.
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:
to: 'poiCategory'draws the SDK’s pin for the categoryfnreturns, so a stop that came from search shows what kind of place it is.to: 'imageID'draws the imagefnnames, from the style’s sprite or fromwaypoints.icon.customIcons.- If
fnreturnsundefinedfor a waypoint, it keeps its role’s pin and stop mark.
const routingModule = await RoutingModule.create(map, { waypoints: { icon: { finish: { image: { image: chequeredFlagSVG } }, mapping: { to: 'poiCategory', fn: (waypoint) => waypoint.properties.poi?.categories?.[0] } } }});- The module draws an image at pixel ratio 2 unless it sets
pixelRatio. It stands on the waypoint by its bottom middle, like the SDK’s 120 × 140 pixel pins. RoutingModuleSerializableConfigkeeps the styles, the stop numbering and images given as a URL, data URI or SVG text. It leaves outmapping, a functiontitleand anHTMLImageElementimage.
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 hiddenawait routingModule.showRoutes(route); // kept, not drawnroutingModule.setVisible(true); // draws the routeroutingModule.isVisible(); // trueshowRoutes,showWaypoints, the clear methods and a style change leave a hidden module hidden.- It sets the config’s
visible, soisVisible()reads the setting back andconfig-changereports it. - While the module is shown, each part’s own
visible(sections.<type>.visible,summaryBubbles.visible, …) still decides whether that part draws.
Events
Each part of a route has its own scope 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));
// Removes every click handler of the scope; `on` returns an unsubscribe for one handlerroutingModule.events.mainLines.off('click');- A scope’s
offalso stops the click handlers ofroutingModule.eventson the route lines, as user events explains. - Route sections covers the section scopes:
ferries,tollRoads,tunnels,vehicleRestricted,countryCrossingsand one<type>Sectionsper generated type. - The instruction arrows have no scope. A click on one is a click on its instruction.
Once a handler covers the routes, a hovered or clicked route draws its outline wider, selected or not. The module’s event state methods act on the routes, and each named scope has them for its own features.
To select a route on click, call selectRoute. It clears the click state of the route lines and summary
bubbles, since the selected style marks the route from then on. The route you clicked loses its wider outline
with the click, and takes it again once the pointer moves on it, if a handler covers the selected route. To keep
the selected route from reacting to the pointer at all, narrow the handler to the alternatives:
routingModule.events.mainLines .where((route) => route.properties.routeState === 'deselected') .on('click', (route) => routingModule.selectRoute(route.properties.index));
routingModule.setEventState({ index: 1, state: 'hover' });route.properties.index is the route’s index in the routing response, while selectRoute takes its position
among the shown routes. The two match when you show every route of the response. When you show only some, pass
the route’s position in the collection you gave showRoutes.
Keep the selected route hoverable when hovering it does something of its own, such as pointing at its card in a list.
highlight.outline.widthFactor sets how much wider. It defaults to 1.2 and is clamped to 1 to 1.25. A section
halo beneath the route is wider still, so it keeps a thin edge while the
route is hovered and shows in full again once the pointer leaves. 1 draws a hovered route like any other. An outline width you set through layers.mainLines.routeOutline stays as you set it, 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 are mainLines, waypoints, incidents, ferries, tollRoads, tunnels,
vehicleRestricted, instructionLines, instructionArrows, summaryBubbles, countryCrossings and
sectionFocus, plus one <type>Sections per
generated section type, such as urbanSections and
motorwaySections.
API reference
RoutingModule lists every method, and
RoutingModuleConfig every setting.
Related guides and examples
Services integration
- Route planning parameters - Every option of
calculateRoute - Locations - Specifying route planning locations
- Guidance - The turn-by-turn instructions the module draws
- Geocoding - Addresses to coordinates for waypoints and destinations
Related examples
- Route - Basic route calculation and display on the map
- Route with alternatives - Display multiple route options for comparison
- Waypoints - Multi-stop route visualization with interactive waypoints
- Map route reconstruction playground - Interactive route building and editing
- Route stop wait playground - A stop’s wait on its pin, and in the journey time
- Route style playground - The route’s colour, width, waypoint size, waypoint label colour and clicked outline on knobs, and a toggle that hides it
- Route sections playground - Every section type on one set of knobs, and the speed-limit sign controls
- Route waypoints playground - Per-role pins, stop numbering, labels, hover growth, a category pin per stop and a finish image of your own
- Speed limit signs by country - A section’s number posted as the road sign its country uses
- Display units - Summary bubbles and speed limit signs relabelled by the global
displayUnits - Borrowed looks - A route’s traffic sections recoloured live by the incident colour knobs
Related map modules
- Route styling - The route’s own look and its knob catalogue
- Route sections - The overlays drawn per stretch of road
- Places module - The places a user is still choosing among, before one joins the route as a waypoint
- User interaction events - Handle user interactions with routes and route segments