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.
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.get(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); // clearCustomising or disabling the focus treatment
The default visual is opinionated but not baked in — pass a focus config to
TrafficIncidentOverlayModule.get(map, …):
// Override individual fields (the others fall back to defaults).const overlay = await TrafficIncidentOverlayModule.get(map, { focus: { outlineColor: '#1976d2', widthScale: 2 },});// 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.get(map, { focus: false });Visibility and layer ordering
overlay.setVisible(false);overlay.setVisible(true);
// Place the overlay above all other layers (default: below labels):overlay.moveBeforeLayer('top');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:
- No road-class-aware width/offset (every incident is a uniform stripe centred on the road).
- No declutter — every incident shows above the layer minzoom.
- No secondary cause icon overlay (only the primary category icon renders).
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().