Maps SDK for JavaScript
Back to all examples
Mixed User Interaction Events
Handle various map events and user interactions
import { Place, TomTomConfig } from '@tomtom-org/maps-sdk/core'; import { BaseMapModule, PlacesModule, TomTomMap, TrafficIncidentsModule } from '@tomtom-org/maps-sdk/map'; import { reverseGeocode, search } from '@tomtom-org/maps-sdk/services'; import { LngLat, MapGeoJSONFeature, Marker, NavigationControl, Popup } from 'maplibre-gl'; import './style.css'; import { API_KEY } from './config'; // (Set your own API key when working in your own environment) TomTomConfig.instance.put({ apiKey: API_KEY }); (async () => { const map = new TomTomMap({ container: 'sdk-map', center: [-0.12634, 51.50276], zoom: 14, }); const popUp = new Popup({ closeButton: true, closeOnClick: true, closeOnMove: true, offset: 15, className: 'sdk-example-popup', }); let isMarkerVisible = false; const revGeocodingMarker = new Marker({ color: '#df1b12' }); const showTrafficPopup = (topFeature: MapGeoJSONFeature, lngLat: LngLat) => { const { properties } = topFeature; const incidentSeverity: Record<number, string> = { 3: 'major', 2: 'moderate', 1: 'minor', }; popUp .setOffset(5) .setHTML( ` <div id="traffic-incident-popup"> <h3>Traffic incident</h3> <b id="traffic-incident-road-type">Road type</b> ${topFeature.properties.road_category}<br /> <b id="traffic-incident-magnitude">Magnitude</b> ${incidentSeverity[properties.magnitude]} <br /> <b id="traffic-incident-delay">Delay</b> ${Math.floor(properties.delay / 60)} m ${ properties.delay % 60 } s</b> <br /> </div> `, ) .setLngLat(lngLat) .addTo(map.mapLibreMap); }; const initTrafficIncidents = async () => { (await TrafficIncidentsModule.get(map, { visible: true })).events.on('long-hover', showTrafficPopup); }; const showPlacesPopUp = (topFeature: Place, lngLat: LngLat) => { const { address, poi } = topFeature.properties; if (isMarkerVisible) { revGeocodingMarker.remove(); } new Popup({ closeButton: true, closeOnClick: true, closeOnMove: true, offset: 15, className: 'sdk-example-popup', }) .setHTML( ` <div id="place-popup"> <h3 id="place-name">${poi?.name}</h3> <b id="place-address"> Address: </b> ${address.freeformAddress} <br /> ${poi?.phone ? `<b> Phone: </b> ${poi?.phone}` : ''} <div id="sdk-example-popup-tags"> ${poi?.categories?.map((category) => `<span class="sdk-example-popup-tags-item">${category}</span>`)} </div> </div> `, ) .setLngLat(lngLat) .addTo(map.mapLibreMap) .once('close', () => (isMarkerVisible = true)); }; const initPlacesModule = async () => { const placesModule = await PlacesModule.get(map); const places = await search({ query: 'pharmacy', limit: 35, boundingBox: map.getBBox(), }); placesModule.show(places); placesModule.events.on('click', showPlacesPopUp); }; const showBasemapPopup = async (_: any, lnglat: LngLat) => { const { properties } = await reverseGeocode({ position: [lnglat.lng, lnglat.lat] }); revGeocodingMarker.setLngLat(lnglat).addTo(map.mapLibreMap); if (!isMarkerVisible) { new Popup({ closeButton: true, closeOnClick: true, closeOnMove: true, offset: 6, className: 'sdk-example-popup-basemap', }) .setHTML( ` <div id="sdk-example-popup-basemap"> ${ properties.address.freeformAddress ? ` <h4 id="sdk-example-popup-basemap-address">${properties.address.freeformAddress}</h4> <hr class="sdk-example-hr" />` : '' } <div id="sdk-example-popup-lnglat"> <span> ${lnglat.lng.toFixed(5)}, ${lnglat.lat.toFixed(5)}</span> </div> </div> `, ) .setLngLat(lnglat) .addTo(map.mapLibreMap); isMarkerVisible = true; } else { revGeocodingMarker.remove(); isMarkerVisible = false; } }; const initBaseMapModule = async () => { const baseModule = await BaseMapModule.get(map); // Listening hover events on Basemap module to remove traffic popups. baseModule.events.on('hover', () => popUp.isOpen() && popUp.remove()); baseModule.events.on('click', showBasemapPopup); }; map.mapLibreMap.addControl(new NavigationControl()); map.mapLibreMap.on('dragstart', () => { revGeocodingMarker.remove(); isMarkerVisible = false; }); await initBaseMapModule(); await initPlacesModule(); await initTrafficIncidents(); })();
Related examples
Interactive roads and numbers
Base Map with interactive roads and house numbers.
Base Map
Web
Playground
User Interaction Events
Map autocomplete fuzzy search playground
Combine autocomplete search with fuzzy search functionality
Places and Search
Playground
Web
User Interaction Events
Geometries playground
Display multiple geographic geometries with different configurations
Playground
Base Map
Map Style
Geometry
Web