Hi All
I am trying to add the ability to click on the traffic icons to view the traffic information on my map.
I have been mostly following the examples of the two below SDK live examples:
- Traffic Incidents List
- Custom Incident Markers and Popups
I am encountering an issue with the below function where when it runs after you click on an icon the ‘feature’ is coming through as undefined:
function addPopup(feature, detailsFeatures) {
var details;
if (detailsFeatures) {
detailsFeatures.forEach(function(detailFeature) {
if (detailFeature.properties.id === feature.properties.id) {
details = detailFeature.properties;
}
});
}
closePopup();
if (details) {
state.popup = new tt.Popup({
offset: [0, -20], className: ‘tt-popup’
})
.setLngLat(feature.geometry.coordinates)
.setHTML(createCustomPopupHTML(feature.properties, details))
.addTo(map);
}
}
Full html code below:
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel='stylesheet' type='text/css' href='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/maps/maps.css'>
<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/index.css'/>
<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/icons-css/poi.css'/>
<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/icons-css/traffic-incidents.css'/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/javascript-debounce@1.0.1/dist/javascript-debounce.min.js'></script>
<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/maps/maps-web.min.js'></script>
<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/services/services-web.min.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/tail.select.min.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/formatters.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/info-hint.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/foldable.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/mobile-or-tablet.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/search/side-panel.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/traffic/incidents-details-manager.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/traffic/incident-marker.js'></script>
<script type='text/javascript' src='./tomtomMapAssets/js/search/dom-helpers.js'></script>
<script type="text/javascript">
$(document).ready(function () {
const queryString = window.location.href;
const urlParams = (new URL(queryString).searchParams);
const lat = urlParams.get('lat')
const lng = urlParams.get('lng')
const tomtomMapApiKey = 'XXXXXXXXXXX';
const TRAFFIC_INCIDENTS_STYLE = 's0';
let tomtomMap = tt.map({
key: tomtomMapApiKey,
container: 'map',
center: [lng, lat],
zoom: 15,
dragPan: true, //!isMobileOrTablet()
stylesVisibility: {
trafficIncidents: true,
trafficFlow: true
}
});
var state = {
popup: undefined,
popupIncidentLayer: undefined,
featureId: undefined,
loadingPopup: false
};
var errorHint = new InfoHint('error', 'bottom-center', 5000).addTo(document.getElementById('map'));
var loadingHint = new InfoHint('info', 'bottom-center').addTo(document.getElementById('map'));
loadingHint.setMessage('Loading...');
tomtomMap.addControl(new tt.FullscreenControl());
tomtomMap.addControl(new tt.NavigationControl());
tomtomMap.on('load', function() {
getIncidentLayers().forEach(function(layerId) {
tomtomMap.on('click', layerId, function(event) {
onIncidentClick(event, layerId);
});
});
performIncidentDetailsRequest().then(function(incidentDetailsResponse) {
if (incidentDetailsResponse.length) {
var feature = incidentDetailsResponse[0];
tomtomMap.setCenter(feature.geometry.coordinates);
tomtomMap.setZoom(15);
}
state.popup = new tt.Popup({ className: 'tt-popup', offset: 20 })
.setHTML('Click on any incident marker to open a popup.')
.setLngLat(tomtomMap.getCenter())
.addTo(tomtomMap);
}).catch(function(error) {
errorHint.setMessage(error);
}).finally(function() {
loadingHint.hide();
});
});
function onIncidentClick(event, layerId) {
if (state.loadingPopup) {
return;
}
state.loadingPopup = true;
var feature = event.features[0];
state.featureId = feature.properties.id;
tomtomMap.panTo(feature.geometry.coordinates, {duration: 200});
performIncidentDetailsRequest().then(function(incidentDetailsResponse) {
addPopup(feature, incidentDetailsResponse);
state.popupIncidentLayer = tomtomMap.getLayer(layerId);
}).catch(function(error) {
errorHint.setMessage(error);
}).finally(function() {
state.loadingPopup = false;
});
}
function getIncidentLayers() {
return tomtomMap.getStyle().layers.filter(function(layer) {
return layer.source === 'vectorTilesIncidents' && layer.type === 'symbol';
}).map(function(layer) {
return layer.id;
});
}
function performIncidentDetailsRequest() {
return tt.services.incidentDetailsV5({
key: tomtomMapApiKey,
boundingBox: tomtomMap.getBounds(),
fields: `{
incidents {
type,
geometry {
type,
coordinates
},
properties {
id,
iconCategory,
magnitudeOfDelay,
events {
description,
code,
iconCategory
},
from,
to,
length,
delay,
roadNumbers
}
}
}`
}).then(data => {
return data.incidents.map(el => ({
geometry: {
coordinates: el.geometry.coordinates[0],
type: 'Point'
},
properties: el.properties,
type: el.type
}));
});
}
function addPopup(feature, detailsFeatures) {
var details;
if (detailsFeatures) {
detailsFeatures.forEach(function(detailFeature) {
if (detailFeature.properties.id === feature.properties.id) {
details = detailFeature.properties;
}
});
}
closePopup();
if (details) {
state.popup = new tt.Popup({
offset: [0, -20], className: 'tt-popup'
})
.setLngLat(feature.geometry.coordinates)
.setHTML(createCustomPopupHTML(feature.properties, details))
.addTo(map);
}
}
function closePopup() {
if (state.popup) {
state.popup.remove();
}
state.popup = undefined;
state.popupIncidentLayer = undefined;
state.incidentId = undefined;
}
function createCustomPopupHTML(properties, details) {
var photo = photosMapping[properties.description_0] || photosMapping.default;
var description = details.events[0].description || properties.description_0;
return (
'<div class="tt-traffic-details -column">' +
'<div class="details-header">' +
'<img class="custom-img -' +
details.incidentSeverity + '" src="../assets/images/custom-incident-markers/' + photo + '">' +
'<div>' +
(details.roadNumbers.length ?
'<div class="tt-road-shield">' + details.roadNumbers + '</div>' : '') +
'</div>' +
'</div>' +
'<div class="tt-traffic-description">' +
'<div class="tt-incident-category">' + description + '</div>' +
'</div>' +
createCustomPopupDetailsContentHTML(details) +
'</div>'
);
}
function createCustomPopupDetailsContentHTML(details) {
if (!details) {
return '';
}
return (
'<div class="details-content">' +
'<div>' +
(details.delay ?
'<div><label>Delay:</label> ' +
Formatters.formatToDurationTimeString(details.delay) + '</div>' :
'') +
'<div>' +
'<label>Traffic length:</label> ' +
Formatters.formatAsMetricDistance(details.length) +
'</div>' +
'</div>' +
'<div><label>From:</label> ' + details.from + '</div>' +
'<div><label>To:</label> ' + details.to + '</div>' +
'</div>'
);
}
});
</script>
<div id="map" class="map"></div>