Maps SDK for JavaScript
Back to all examples
Map reachable ranges from multiple locations
Calculate time-based accessibility areas from multiple locations
import { TomTomConfig } from '@tomtom-org/maps-sdk/core'; import { type ColorPaletteOptions, GeometriesModule, type GeometryBeforeLayerConfig, type GeometryTheme, PlacesModule, reachableRangeGeometryConfig, type StandardStyleID, TomTomMap, } from '@tomtom-org/maps-sdk/map'; import { type BudgetType, calculateReachableRanges } from '@tomtom-org/maps-sdk/services'; import type { LngLatBoundsLike } from 'maplibre-gl'; import './style.css'; import { API_KEY } from './config'; import { getBudgetsForMax, initControls, setStatus } from './controls'; import { getVehicleForBudgetType } from './vehicleProfiles'; // (Set your own API key when working in your own environment) TomTomConfig.instance.put({ apiKey: API_KEY }); let origin: [number, number] = [4.7641, 52.3086]; let currentTheme: GeometryTheme = 'filled'; let currentPalette: ColorPaletteOptions = 'fadedRainbow'; let currentBudgetType: BudgetType = 'timeMinutes'; let currentBeforeLayer: GeometryBeforeLayerConfig = 'lowestLabel'; let maxBudget = 30; const map = new TomTomMap({ style: 'monoDark', mapLibre: { container: 'sdk-map', center: origin, zoom: 9 }, }); (async () => { const originPin = await PlacesModule.get(map); const geometriesModule = await GeometriesModule.get( map, reachableRangeGeometryConfig(currentPalette, currentTheme, currentBeforeLayer), ); let lastResult: Awaited<ReturnType<typeof calculateReachableRanges>> | null = null; let abortController = new AbortController(); const formatCoords = ([lng, lat]: [number, number]) => `${lat.toFixed(4)}, ${lng.toFixed(4)}`; const isInvertedTheme = (theme: GeometryTheme) => theme === 'inverted'; const updateRanges = async (fitBounds = true) => { abortController.abort(); abortController = new AbortController(); setStatus('', true); try { const result = await calculateReachableRanges( getBudgetsForMax(maxBudget, currentBudgetType, isInvertedTheme(currentTheme)).map((value) => ({ origin, budget: { type: currentBudgetType, value }, vehicle: getVehicleForBudgetType(currentBudgetType), })), { signal: abortController.signal }, ); if (!result.features.length) { geometriesModule.clear(); setStatus('No ranges found for this location.'); return; } lastResult = result; geometriesModule.show(result); if (fitBounds && result.bbox) { map.mapLibreMap.fitBounds(result.bbox as LngLatBoundsLike, { padding: 50 }); } setStatus(''); } catch { // AbortError — a newer call is already in flight } }; const refreshDisplay = () => { if (lastResult?.features.length) { geometriesModule.applyConfig( reachableRangeGeometryConfig(currentPalette, currentTheme, currentBeforeLayer), ); void geometriesModule.show(lastResult); } }; const showPin = (lngLat: [number, number], label = '') => { originPin.show({ type: 'Feature', id: 'origin', geometry: { type: 'Point', coordinates: lngLat }, properties: { type: 'Point Address', address: { freeformAddress: label } }, }); }; const setOrigin = (lngLat: [number, number], label?: string) => { origin = lngLat; showPin(lngLat, label); updateRanges(); }; const controls = initControls(map, { onOriginSelected: (lngLat, displayName) => setOrigin(lngLat, displayName), onBudgetTypeChange: (type, newMax) => { currentBudgetType = type; maxBudget = newMax; updateRanges(); }, onMaxBudgetChange: (max) => { maxBudget = max; updateRanges(); }, onPaletteChange: (palette) => { currentPalette = palette; refreshDisplay(); }, onThemeChange: (theme) => { currentTheme = theme; refreshDisplay(); }, onStyleChange: (styleId: StandardStyleID) => { map.setStyle(styleId); }, onBeforeLayerChange: (beforeLayer) => { currentBeforeLayer = beforeLayer; geometriesModule.moveBeforeLayer(beforeLayer); }, }); // Click/touch on map to relocate origin map.mapLibreMap.on('click', (e) => { const lngLat = e.lngLat.toArray(); controls.setOriginInput(formatCoords(lngLat)); setOrigin(lngLat); }); showPin(origin); controls.setOriginInput(formatCoords(origin)); updateRanges(); })();
Related examples
Add Stops to Route
Dynamically add and remove intermediate stops on a route by clicking the map
Routing
Web
Playground
Utilities
Keep state when changing style
SDK modules preserve state when switching map styles
Routing
Map Style
Web
Long Distance EV Routing with detailed vehicle
A-B Long Distance EV Route with charging stops and detailed vehicle parameters.
Routing
Electric Vehicles
Web
Long Distance EV Routing charging stops customization
A-B Long Distance EV Route with charging stops having custom icons and text.
Routing
Electric Vehicles
Web
Customization