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

Map modules

A map module adds one capability to a TomTomMap: showing places or routes, filtering traffic, shading terrain, restyling the whole map. Every module shares one contract, which this page owns:

Types of modules

Who owns the sources and layers a module controls decides both the factory you call and how many instances make sense on one map.

Style-owned modules — get(map, config?)

Data-owned modules — create(map, config?)

Per-module reference

Module Kind What it draws or controls
BaseMapModule Style-owned Which base-map layer groups and road parts show, and the events on them
POIsModule Style-owned The style's POIs: visibility, category filters, size, labels, category icons
TrafficFlowModule Style-owned The live traffic flow tiles
TrafficIncidentsModule Style-owned The live traffic incident tiles
TerrainModule Style-owned Hillshade shading and the 3D surface
StylingFoundationsModule Style-owned Sizes, map colours, projection and sky across the whole map
PlacesModule Data-owned Places you give it, as pins, circles or base-map-looking icons
RoutingModule Data-owned Routes, waypoints and route sections
GeometriesModule Data-owned Polygons and lines, such as administrative areas
ReachableRangesModule Data-owned The bands calculateReachableRanges returns
CustomGeoJSONModule Data-owned Your own GeoJSON, with your own MapLibre layer specs
TrafficIncidentDetailsModule Data-owned Incidents you fetched with trafficIncidentDetails
TrafficAreaAnalyticsModule Data-owned Area analytics as a hexgrid, square grid or heatmap

Who owns what

Everything visible on the map has exactly one owner, and the owner follows from who owns the layers. Every module has knobs of its own: each style-owned module decides whether and how its part of the loaded style shows, the Styling Foundations module the foundations that reach across every part — sizes, the map colours, projection and sky — and each data-owned instance everything about the layers it adds itself. The dashed line is the only place a knob reaches past its module: the data-owned modules read the accent as their default colour.

Style-owned modules: get(), one per mapStylingFoundationsModule: get(), one per mapData-owned modules: create(), many per mapMapLibre mapBaseMapModule · POIsModuleTrafficFlowModule · TrafficIncidentsModuleTerrainModuleTheir knobs: what is shown, and howvisible · filters · road partsPOI, traffic and hillshade looksIts knobs: the foundations of the whole mapsizes · map colours · projection · skycolors.accentPlacesModule · RoutingModule · GeometriesModuleReachableRangesModule · CustomGeoJSONModuleTrafficIncidentDetailsModule · TrafficAreaAnalyticsModuleEach instance's own knobscolor · label · width · markerType · …The loaded style's layersbase map · POIs · traffic tiles · hillshadeMap viewprojection · skySources and layers each instance adds(ids suffixed per instance) show, hide, filter, restylerestyle every partview.* knobs default colour, readdraw and style

In detail:

You want to change… Owner How
Whether something the loaded style draws is shown — a base-map layer group or road part, the traffic tiles, a POI category, the hillshade, the 3D surface The style-owned module for that part setVisible, updateConfig({ filters }), setHillshadeVisible, setElevationVisible, setKnob
How one part looks — POI size and label colours, traffic colours and widths, hillshade lighting The style-owned module for that part: POIs, traffic flow, traffic incidents, terrain setKnob, updateConfig
The foundations across every part — label, icon and road sizes, the ten map colours, projection and sky The Styling Foundations module setKnob, setMapColors
A named bundle of looks across those modules applyMapPreset applyMapPreset(map, id)
Anything a data-owned module draws itself — routes, places, geometries, your GeoJSON, fetched traffic incidents, area analytics That module, through its own configuration create(map, config), applyConfig / updateConfig, setKnob and setVisible
The map's colour identity — the accent routes, places and geometries default to The Styling Foundations module publishes it; each data-owned module reads it setMapColors, the colors.accent knob; a colour set on the module always wins
A look a data-owned module borrows from the style, such as POI-looking places or the colours of fetched traffic incidents The module whose knob restyles it sets it on the style; the data-owned module reads it and redraws its own layers The knobs that restyle what it borrows; a setting given to the module always wins

Two consequences:

Within a style-owned module, the finer settings only narrow what its coarser ones show. A road part or the POI micro markers never show while their layer group or the POIs are hidden, and showing those again keeps a part's false; the POIs' zoomShift rewrites the same layer filters filters.categories narrows, in either order.

Each module guide opens with a What this module owns line that applies this rule to that module.

Changing a setting

Every setting changes through three calls each module has: applyConfig(config) replaces the whole configuration, updateConfig(partial) changes the top-level properties it is given, and setKnob sets one setting by its catalogue id.

Saving and replaying a configuration

getConfig() is the export and applyConfig() the import: a module's configuration that went through JSON, given back to applyConfig, holds the same configuration and draws the same layers. Keep one to restore a user's map, attach it to a support report, or replay it in a test.

localStorage.setItem('places', JSON.stringify(placesModule.getConfig()));

// Later, on the same module or a new one
placesModule.applyConfig(JSON.parse(localStorage.getItem('places')));

Most modules' configurations are JSON whole, styling's knobs included. Five modules also take functions or image elements, which JSON cannot carry. Each has a type for the part that survives, which its reference page details; a replay adds the rest back in code:

Module Serializable part Left out
PlacesModule PlacesModuleSerializableConfig label.title as a function, connections.label.title, evAvailability.formatText, icon.mapping, extraFeatureProps functions, image elements in icon
RoutingModule RoutingModuleSerializableConfig a custom chargingStops.icon.mapping, waypoints.icon.mapping, waypoints.label.title as a function, image elements in chargingStops.icon and waypoints.icon
GeometriesModule GeometriesModuleSerializableConfig transformFeaturesForDisplay
ReachableRangesModule ReachableRangesModuleSerializableConfig lineLabel.title
CustomGeoJSONModule CustomGeoJSONModuleSerializableConfig images

JSON.stringify drops a function without a trace, but turns an image element into {}, which does not replay. Give icon images as URLs, data URIs or SVG text, and a place or waypoint title as a MapLibre expression, to keep the whole configuration serializable. POIsModule's icon.categoryIcons takes image elements too, with no type to leave them out.

const state = JSON.parse(saved); // PlacesModuleSerializableConfig
placesModule.applyConfig({
    ...state,
    connections: { ...state.connections, label: { ...state.connections?.label, title: (connection) => connection.name } },
});

The configuration is what a module draws with, not the data it shows: replay show() with the data too.

Appearance vocabulary

A concept has one name on every module that has it. The table lists the shared appearance terms, the rule each follows, and the exact properties that carry it; a module missing from a row does not have that concept.

Concept The rule Modules and properties
The module's colour A top-level color is the colour of what the module draws. Unset, it is the map's accent (colors.accent, published as map.mapColors.accent), then the module's own default. A part-level colour overrides it. RoutingModule: color, under layers.* paint overrides · GeometriesModule: color, under fill.palette, fill.color, line.color and a feature's color property (order) · PlacesModule: color, under icon.default.style.fillColor, label.color and layers.*
Labels One label shape, LabelConfig: size, color, haloColor, haloWidth, opacity, font. Each module adds the label's content and its own offset; FeatureLabelConfig adds a title, a function or a MapLibre expression. PlacesModule: label (PlaceLabelConfig, adds title, and offset as one number of ems away from the icon) · RoutingModule: waypoints.label (WaypointLabelConfig, adds title and visible), and chargingStops.label (ChargingStopLabelConfig: visible and a title expression, without the LabelConfig styling) · GeometriesModule: label (GeometryLabelConfig, adds text, a string or expression that defaults to the feature's title), and lineLabel (GeometryLineLabelConfig, the same text plus minZoom, symbolSpacing, and offset as [x, y] ems) · ReachableRangesModule: lineLabel (ReachableRangeLineLabelConfig, adds a title function)
Multipliers A *Factor multiplies a default and is clamped to its catalogue entry's range, which knobEntryOf(catalogue, id) reads. Where a size also has presets ('s', 'm', 'l'), the preset picks the base and the factor multiplies it. RoutingModule: width and widthFactor (0.5 to 2), waypoints.size and waypoints.sizeFactor (0.5 to 2), sections.<type>.width and sections.<type>.widthFactor, sections.<type>.icon.sizeFactor (0.25 to 2), highlight.outline.widthFactor (1 to 1.25), waypoints.highlight.sizeFactor (1 to 1.5) · GeometriesModule: highlight.fill.opacityFactor (1 to 4) and highlight.line.widthFactor (1 to 3) · TrafficIncidentDetailsModule: highlight.line.widthFactor (1 to 1.8) · POIsModule: sizeFactor (0.5 to 1.5) · TrafficFlowModule and TrafficIncidentsModule: widthFactor (0.5 to 2) · Styling Foundations knobs: labels.sizeFactor, symbols.sizeFactor, roads.widthFactor (0.5 to 1.5)
Hovered and clicked look A feature a handler covers, or one setEventState puts a state on, draws one look whether hovered or clicked. highlight holds the factors that look multiplies by; a factor of 1 draws the feature as any other. A MapLibre layer you give in place of the default draws as given. RoutingModule: highlight.outline.widthFactor, waypoints.highlight.sizeFactor · GeometriesModule: highlight.fill.opacityFactor, highlight.line.widthFactor · TrafficIncidentDetailsModule: highlight.outline.color, highlight.line.widthFactor, also drawn on the incidents setFocus marks, highlight: false to turn it off · PlacesModule: layers.selected
Absolute units A value that mirrors a MapLibre property keeps MapLibre's name and is in pixels. Any other unit is in the name. Opacities run from 0 to 1, label offsets are in ems. Pixels: LabelConfig size and haloWidth, GeometriesModule line.width and lineLabel.symbolSpacing, PlacesModule cluster.badge.outlineWidth and cluster.badge.radius · Metres: TrafficAreaAnalyticsModule maxHeightMeters, minHeightMeters and, per unit of the metric, metersPerUnit · Two exaggerations: TerrainModule elevation.exaggeration scales the raised surface, its hillshade.exaggeration sets the shading strength
Marker type, fill style, map theme Theme means only the map-wide look. How one module draws its own features has a name of its own. PlacesModule: markerType (PlacesMarkerType; placesMarkerTypes lists pin, circle-icon, base-map, pin-clustered) · GeometriesModule: fillStyle (GeometryFillStyle; geometryFillStyles lists filled, outline, inverted), per feature properties.fillStyle · ReachableRangesModule: fillStyle, the same values · Map theme: StylingFoundationsModule.setMapColors, fed by the Map Theme plugin's deriveMapColors, deriveMapColorsFromCss, deriveMapColorsFromImage and mapColorsLightDark
Fill colour or palette A colour field takes a colour or a MapLibre expression, never a palette name. A palette is its own field: on geometries and reachable ranges a list of your own CSS colours, which the features or bands take one after another; on area analytics a name, ramped over the metric's value. GeometriesModule: fill.color, fill.palette, unset drawing one colour, the accent · ReachableRangesModule: fill.palette, unset ramping from the accent toward the map's land colour · TrafficAreaAnalyticsModule: metrics.<metric>.palette (AreaAnalyticsPalette; areaAnalyticsPalettes lists the names), and metrics.<metric>.colorStops, which wins over it
Zoom thresholds minZoom and maxZoom. PlacesModule: entryPoints.minZoom · GeometriesModule: lineLabel.minZoom · RoutingModule: sections.<type>.sign.minZoom, countryCrossings.minZoom · POIsModule: minZoom · TerrainModule: hillshade.maxZoom
Borrowed looks A part drawn to look like the style follows the knobs that restyle what it borrows. A look set on the module wins. PlacesModule with markerType base-map, circle-icon or pin-clustered · RoutingModule sections.traffic · TrafficIncidentDetailsModule line colours. The knobs each one follows: Borrowed looks
Visibility visible in the config, setVisible(visible) to change it, isVisible() to read it back. isVisible() returns the setting, the same value as the module's visible knob. On a data-owned module, hiding keeps the data, show() and clear() leave it hidden, and getShown() returns what is shown. On a style-owned module that nothing has set, isVisible() reads what the style draws, and the traffic modules are hidden until shown; getRenderedFeatures() returns what its tiles render in view. A part that hides on its own has its own visible. All three on PlacesModule, RoutingModule, GeometriesModule, ReachableRangesModule, CustomGeoJSONModule, TrafficIncidentDetailsModule, TrafficAreaAnalyticsModule, POIsModule, TrafficFlowModule and TrafficIncidentsModule (plus icons.visible with setIconsVisible / isIconsVisible) · BaseMapModule: visible, groups.<group>.visible, setVisible and isVisible with { layerGroups } · RoutingModule per part: chargingStops.visible, chargingStops.label.visible, summaryBubbles.visible, countryCrossings.visible, sections.<type>.visible · TerrainModule: hillshade with setHillshadeVisible / isHillshadeVisible, elevation with setElevationVisible / isElevationVisible
Layer position beforeLayerConfig takes 'top' or a named style layer such as 'lowestLabel' (BeforeLayerConfig) for all of a module's layers. A module drawing several parts also takes a record keyed by its part names, all covering the parts it leaves out (PartsBeforeLayerConfig). GeometriesModule and ReachableRangesModule: GeometryBeforeLayerConfig, parts fill, line · RoutingModule: RoutingBeforeLayerConfig, parts mainLines, instructionLines, icons · PlacesModule: PlacesBeforeLayerConfig, parts places, connections · TrafficAreaAnalyticsModule: AreaAnalyticsBeforeLayerConfig, one part per display mode · TrafficIncidentDetailsModule: BeforeLayerConfig alone · CustomGeoJSONModule: CustomGeoJSONBeforeLayerConfig, for all its layers and on each layer, which also takes { layerID } to go below a layer outside the style
Value filters One filter shape, ValuesFilter: { show, values }, where show is one of filterShowModes, 'only' (just the values) or 'all-except' (everything but them). POIsModule: filters.categories · TrafficFlowModule and TrafficIncidentsModule: filters fields such as roadCategories and, on incidents, magnitudes · BaseMapModule: the layerGroups that setVisible, isVisible and events.where take

Every setting as data

A module's display settings are also published as a knob catalogue: static data, readable with no map loaded, that a control panel builds its controls from and an agent checks a value against. An entry's id is the setting's path in the module's configuration, where a number indexes a list (filters.any.0), and its kind says which value it takes and which fields come with it. The entry type is KnobEntry, and the kinds are KnobKind:

Kind Value Fields
toggle true or false
factor a multiplier, 1 keeping what the style does range
number a number range
offset an [x, y] displacement, x to the right and y down, in the unit the description names range, for x and y each
color a CSS colour
enum one of the options options
enums a list of the options; the description says when their order matters options
colors a list of CSS colours or of the names in options options, where there are names
image the id of an image in the style's sprite
text any string

Setting a knob by its id

Three functions work a knob by its catalogue id, on every module, the Styling Foundations module and the map effects plugin's MapEffects included:

The path is the same for every module, and a knob only ever redraws what its own module draws:

One catalogue per modulestatic data, no map neededA valuefrom a control, saved settings or an agentSet one knob by idvalidateKnobValueagainst the entryRangeErrornothing changesThat module's configurationone setting changed, the rest keptWhat that module draws, and nothing elseevents: 'config-change'placesKnobCatalogueroutingKnobCataloguetrafficFlowKnobCatalogue…stylingFoundationsKnobCatalogueeffectKnobCatalogue (map effects plugin)Each entry: id · kind · range or options · defaultkinds shared by every cataloguesetKnob(module, catalogue, id, value) the entry for the id invalidvalidredraw
import { getKnob, knobEntryOf, resetKnob, setKnob, trafficFlowKnobCatalogue, validateKnobValue } from '@tomtom-org/maps-sdk/map';

setKnob(trafficFlow, trafficFlowKnobCatalogue, 'filters.roadCategories.values', ['motorway', 'trunk']);
getKnob(trafficFlow, trafficFlowKnobCatalogue, 'visible'); // false until set: the entry's default
resetKnob(trafficFlow, trafficFlowKnobCatalogue, 'filters.roadCategories.values');

const knob = knobEntryOf(trafficFlowKnobCatalogue, 'filters.roadCategories.values'); // kind, range or options, default
validateKnobValue(knob, ['motorway', 'cart track']); // RangeError: … 'cart track' is not

The traffic config playground sets every flow and incidents knob this way, from controls built off the two catalogues.