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

Traffic incident overlay module

The Traffic Incident Overlay Module renders incidents fetched from the trafficIncidentDetails() REST service as a developer-controlled overlay. Use this module when you need typed incident objects in your app code — for popups, list views, route correlation, or interactive focus — and want to control exactly when incidents render.

What this module owns: the incident lines and icons it draws from the details you fetched, and how they look — including the focus treatment below. The live incident tiles belong to the Traffic Incidents Module, and their colours to the Styling module. The overlay borrows those colours, so the traffic.incidents.*Color knobs recolour it too (Borrowed looks). No other knob reaches it. See Who owns what.

Looking for something else?

  • The default vector-tile Traffic Incidents Module is the recommended default. It auto-renders all incidents on the map, with full road-class-aware styling and declutter.
  • Use the overlay module when your application already fetches incidents via the REST service and you want the on-map rendering to mirror that exact set — no more, no less.

When to use the overlay vs TrafficIncidentsModule

You need… Use
Live, full-coverage incidents with no fetch TrafficIncidentsModule
Typed incident objects in your app code TrafficIncidentOverlayModule
Render exactly the result of a single REST call TrafficIncidentOverlayModule
Per-feature focus / highlight a subset TrafficIncidentOverlayModule
Maximum visual fidelity (per-road-class styling, declutter) TrafficIncidentsModule

The vector-tile incidents are hidden in the default style, so the overlay does not collide with them out of the box. If you've explicitly enabled TrafficIncidentsModule elsewhere in your app, hide it again before using the overlay to avoid rendering the same incidents twice.

Initialization

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

const map = new TomTomMap({ mapLibre: { container: 'map' } });
const overlay = await TrafficIncidentOverlayModule.create(map);

Rendering incidents

Fetch incidents with the service, then pass the result to show():

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

const result = await trafficIncidentDetails({
    bbox: [4.85, 52.34, 4.95, 52.40],
    timeValidityFilter: ['present'],
});
await overlay.show(result);

show() replaces any previously rendered snapshot. Call clear() to remove all incidents.

Focusing a subset

setFocus(ids) writes MapLibre feature-state on each rendered incident. The default visual treatment widens focused incidents and paints a black outline beneath them; unfocused incidents are unchanged — the focus treatment adds emphasis, it does not dim the rest of the overlay. Pass null to clear focus.

overlay.setFocus(['incident-id-1', 'incident-id-2']);
overlay.setFocus(null); // clear

Customising or disabling the focus treatment

The default visual is opinionated but not baked in — pass a focus config to TrafficIncidentOverlayModule.create(map, …):

// Override individual fields (the others fall back to defaults).
const overlay = await TrafficIncidentOverlayModule.create(map, {
    focus: { outlineColor: '#1976d2', widthFactor: 1.8 },
});

widthFactor multiplies the width of focused incidents. It defaults to 1.6 and is clamped to INCIDENT_FOCUS_WIDTH_FACTOR_RANGE, 1–1.8: 1 keeps the outline without widening, and a wider stripe would cover the outline at high zoom.

// Disable the visual entirely. setFocus() still writes
// `feature-state.focused`, so you can drive your own styling — e.g. extra
// MapLibre layers reading the same feature-state, or a sidebar overlay.
const overlay = await TrafficIncidentOverlayModule.create(map, { focus: false });

focus also changes on a module already showing incidents, its fields and false alike, the focused ones repainting in place:

overlay.updateConfig({ focus: { outlineColor: '#c2185b', widthFactor: 1.2 } });
overlay.updateConfig({ focus: false });

Visibility and layer ordering

isVisible() reports the visible setting, not whether any incident is drawn: an overlay showing nothing still returns true. Read getShown() to know whether incidents are shown. While hidden, show() updates the data without drawing it.

overlay.setVisible(false);
overlay.setVisible(true);
overlay.isVisible(); // true
overlay.getShown().incidents.features.length > 0; // whether incidents are shown

// Place the overlay above all other layers (default: below labels):
overlay.moveBeforeLayer('top');

beforeLayerConfig and moveBeforeLayer take a single target, 'top' or a key of mapStyleLayerIDs — the same shape every module accepts for the whole module. The overlay has no parts to position apart, so there is no record form.

Every setting as data

trafficIncidentOverlayKnobCatalogue lists the module's plain-valued settings with their kind, range and, where one value holds everywhere, their default, readable with no map loaded:

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

const widthFactor = trafficIncidentOverlayKnobCatalogue.find(({ id }) => id === 'focus.widthFactor');
// { id: 'focus.widthFactor', kind: 'factor', description: '…', range: { min: 1, max: 1.8, step: 0.1, bounds: 'hard' }, default: 1.6 }

Limitations

The Incident Details REST API returns a feature list, not a rendering-ready tile. Several tags that the vector-tile pipeline injects per-feature are absent from the REST response, so the overlay renders with reduced visual fidelity:

If you need full visual fidelity, use TrafficIncidentsModule.

Overlapping incidents: when multiple incidents share the same point or stack along the same road segment, MapLibre's symbol collision culling keeps only the highest-sort-key feature. Culled features are not reachable via queryRenderedFeatures. If you need to surface multiple incidents at one location, work directly with the FeatureCollection you passed to show().