Traffic area analytics module
The Traffic Area Analytics Module visualizes historical traffic data for a geographic region on the map. Data is fetched from the TomTom Move Portal API and rendered using one of five visualization modes: 3D or flat hexagonal grids, 3D or flat square grids, or a density heatmap.
Initialization
import { TomTomMap, TrafficAreaAnalyticsModule } from '@tomtom-org/maps-sdk/map';
const map = new TomTomMap({ mapLibre: { container: 'map' } });const analyticsModule = await TrafficAreaAnalyticsModule.create(map);Configure the module at initialization time using a config object:
const analyticsModule = await TrafficAreaAnalyticsModule.create(map, { displayMode: 'hexgrid-3d', activeMetric: 'congestionLevel', metricConfig: { congestionLevel: { color: 'trafficLight' }, },});Fetching and displaying data
Fetch area analytics data using the trafficAreaAnalytics service and pass the response directly to show().
import { geocodeOne, geometryData, trafficAreaAnalytics } from '@tomtom-org/maps-sdk/services';import { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';
// 1. Geocode a city to get its boundaryconst place = await geocodeOne('Amsterdam, Netherlands');const boundary = await geometryData({ geometries: [place] });const regionGeometry = boundary.features[0].geometry;
// 2. Fetch analytics for the last 7 daysconst endDate = new Date();endDate.setDate(endDate.getDate() - 2); // API requires at least 2 days agoconst startDate = new Date(endDate);startDate.setDate(startDate.getDate() - 6);const fmt = (d) => d.toISOString().slice(0, 10);
const analytics = await trafficAreaAnalytics({ apiKey: MOVE_PORTAL_KEY, name: 'Amsterdam, Netherlands', startDate: fmt(startDate), endDate: fmt(endDate), metrics: 'all', functionalRoadClasses: 'all', hours: 'all', geometry: regionGeometry,});
// 3. Display on the mapawait analyticsModule.show(analytics);To remove data from the map:
await analyticsModule.clear();Visualization modes
Five modes are available, set via displayMode at init time or changed at runtime with setMode():
| Mode | Description |
|---|---|
'hexgrid-3d' | 3D extruded hexagonal cells colored and raised by metric value (default) |
'hexgrid-2d' | Flat hexagonal cells colored by metric value |
'square-3d' | 3D extruded square cells colored and raised by metric value |
'square-2d' | Flat square cells colored by metric value |
'heatmap' | MapLibre density heatmap from tile center points |
Switch modes at any time using setMode():
analyticsModule.setMode('heatmap');analyticsModule.setMode('hexgrid-2d');analyticsModule.setMode('square-3d');Metrics
Five metrics are available to drive color and extrusion height. Set the active one via activeMetric. Per-metric style settings (color, height, filters) are configured via metricConfig.
| Metric | Description |
|---|---|
'congestionLevel' | Percentage increase in travel time above free-flow conditions (default active metric) |
'speed' | Average vehicle speed in km/h |
'travelTime' | Average travel time per 10 km in minutes |
'freeFlowSpeed' | Average speed under uncongested conditions in km/h |
'networkLength' | Total road length within each tile in metres — useful as a road density indicator |
analyticsModule.setMetric('speed');analyticsModule.setMetric('travelTime');analyticsModule.setMetric('freeFlowSpeed');You can also pre-configure multiple metrics at init time:
const analyticsModule = await TrafficAreaAnalyticsModule.create(map, { activeMetric: 'congestionLevel', metricConfig: { congestionLevel: { color: 'trafficLight' }, speed: { color: 'heat' }, travelTime: { height: { maxHeightMeters: 300 } }, },});Color
Color configuration is per-metric and set under metric.[metricKey].color. You can use a preset theme name or provide custom color stops.
Preset themes
// Apply a preset theme to all metricsanalyticsModule.setColor('trafficLight'); // green → amber → red (default)analyticsModule.setColor('heat'); // blue → orange → redanalyticsModule.setColor('monochrome'); // light grey → dark greyanalyticsModule.setColor('viridis'); // purple → blue → green → yellowanalyticsModule.setColor('plasma'); // purple → magenta → orange → yellowCustom color stops
Provide an AreaAnalyticsColorStopsConfig object with a valueType and stops array.
'raw' (default) — stop value fields are actual data values:
analyticsModule.setColor({ valueType: 'raw', stops: [ { value: 0, color: '#2dc653' }, // 0% congestion { value: 30, color: '#f5a623' }, // 30% congestion { value: 100, color: '#e03030' }, // 100% congestion ],});'relativeToPredefinedRangePCT' — stop value fields are 0–100 percentages relative to the SDK’s predefined metric ranges (congestion 0–100, speed 0–120 km/h, travelTime 0–20 s/km). Useful for consistent coloring across datasets:
analyticsModule.setColor({ valueType: 'relativeToPredefinedRangePCT', stops: [ { value: 0, color: '#2dc653' }, // 0% of predefined range { value: 50, color: '#f5a623' }, // 50% of predefined range { value: 100, color: '#e03030' }, // 100% of predefined range ],});'relativeToActualRangePCT' — stop value fields are 0–100 percentages relative to the live data range actually present in the loaded tiles (0 % = loaded minimum, 100 % = loaded maximum). Maximises contrast regardless of absolute values:
analyticsModule.setColor({ valueType: 'relativeToActualRangePCT', stops: [ { value: 0, color: '#2dc653' }, // 0% of loaded range { value: 50, color: '#f5a623' }, // 50% of loaded range { value: 100, color: '#e03030' }, // 100% of loaded range ],});Pass undefined to revert to the default 'trafficLight' theme:
analyticsModule.setColor(undefined);For speed, the color order is automatically inverted so that slow speeds render as “bad” (red) and fast speeds as “good” (green).
Height
Height (extrusion) configuration is per-metric under metric.[metricKey].height. Use setHeight() to update the active metric’s height config.
// Predefined range (default): metric normalized to SDK predefined range, visual max = maxHeightMetersanalyticsModule.setHeight({ maxHeightMeters: 200 });
// Set a minimum height flooranalyticsModule.setHeight({ maxHeightMeters: 100, minHeightMeters: 10 });
// Current range: normalizes to live data range — maximises contrast for whatever data is loadedanalyticsModule.setHeight({ maxHeightMeters: 150, scaleMode: 'currentRange' });
// Raw: scaleFactor is multiplied directly with the raw metric value to obtain height in metersanalyticsModule.setHeight({ scaleMode: 'raw', scaleFactor: 10 });Filtering
Filter visible tiles by value range for the active metric using filter(). Only tiles within the given range will be rendered.
// Show only tiles with congestion ≥ 50analyticsModule.filter({ min: 50 });
// Show only tiles within a rangeanalyticsModule.filter({ min: 20, max: 80 });
// Clear the filteranalyticsModule.clearFilter();analyticsModule.filter(undefined); // equivalentRegion boundary
When show() is called, all region polygons in the analytics response are rendered alongside the analytics cells as a subtle fill with an outline. Customize their appearance using regionPolygon:
const analyticsModule = await TrafficAreaAnalyticsModule.create(map, { regionPolygon: { color: '#0052a5', // fill and outline color (default: '#000000') fillOpacity: 0.08, // default: 0 outlineOpacity: 1.0, // default: 0.5 outlineWidth: 3, // default: 2 }});Layer positioning
Control where analytics layers are placed in the map’s rendering stack using beforeLayerConfig. Use 'top' to draw above all layers, or supply a well-known style layer ID to insert the analytics layers below it.
// Place below all labels (default behavior)const analyticsModule = await TrafficAreaAnalyticsModule.create(map, { beforeLayerConfig: { heatmap: 'lowestLabel' },});
// Place everything on topconst analyticsModule = await TrafficAreaAnalyticsModule.create(map, { beforeLayerConfig: { heatmap: 'top', hexgrid: { flat2D: 'top', extrusion3D: 'top' }, },});
// Reposition after initializationanalyticsModule.moveBeforeLayer({ hexgrid: { flat2D: 'lowestLabel', extrusion3D: 'lowestPlaceLabel' },});Visibility
Control overall layer visibility:
// Hidden at startupconst analyticsModule = await TrafficAreaAnalyticsModule.create(map, { visible: false });
// Toggle lateranalyticsModule.setVisible(true);
// Check current stateconsole.log(analyticsModule.isVisible()); // true | falseEvents
Listen to click and hover events on hexgrid and square cells. Events fire for whichever mode is currently active.
analyticsModule.events.on('click', (feature, lngLat) => { console.log('Congestion:', feature.properties.congestionLevel); console.log('Speed:', feature.properties.speed);});
analyticsModule.events.on('hover', (feature) => { console.log('Hovered cell:', feature.properties);});
analyticsModule.events.on('long-hover', (feature) => { console.log('Long-hovered cell:', feature.properties);});
// Remove a specific listeneranalyticsModule.events.off('click');Custom tooltip on hover
Use events.on('hover') to build a hover tooltip:
import { Popup } from 'maplibre-gl';
const popup = new Popup({ closeButton: false, anchor: 'left', offset: 12 });
analyticsModule.events.on('hover', (feature, lngLat) => { if (!feature) { popup.remove(); return; } const { congestionLevel, speed } = feature.properties; popup .setLngLat(lngLat) .setHTML(`<strong>Congestion:</strong> ${congestionLevel ?? 0}%<br/><strong>Speed:</strong> ${speed ?? 0} km/h`) .addTo(map.mapLibreMap);});
map.mapLibreMap.getCanvas().addEventListener('mouseleave', () => popup.remove());Config change events
Subscribe to config changes emitted whenever a setter is called:
const unsub = analyticsModule.events.on('config-change', (config) => { console.log('Active metric:', config?.activeMetric);});// Later: unsub();Querying shown features
Use getShown() to access the GeoJSON feature collections currently rendered for each visualization mode:
const { heatmap, hexgrid, square } = analyticsModule.getShown();console.log(`Hexagonal cells in view: ${hexgrid.features.length}`);API reference
For complete documentation of all properties, methods, and types, see the TrafficAreaAnalyticsModule API Reference.
Related guides and examples
Traffic overview
- Traffic Overview - Overview of all traffic visualization options
Related traffic modules
- Traffic Flow Module - Real-time traffic speed conditions across the road network
- Traffic Incidents Module - Real-time traffic events and incidents
Related examples
- Traffic Area Analytics - Basic area analytics with a geocoded location
- Traffic Area Analytics Playground - Full-featured playground with city search, legend, and tooltips
- Traffic Area Analytics Config Playground - 2D/3D mode toggle and custom color pickers