-
Notifications
You must be signed in to change notification settings - Fork 452
/
Show traffic along route.html
267 lines (218 loc) · 12.2 KB
/
Show traffic along route.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<!DOCTYPE html>
<html lang="en">
<head>
<title>Show traffic along route - Azure Maps Web SDK Samples</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="This sample shows how to retrieve traffic information along a route using the <b>sectionType</b> option, and color the sections on the map. " />
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, services, module, route, directions, route sections, traffic" />
<meta name="author" content="Microsoft Azure Maps" /><meta name="version" content="1.0" />
<meta name="screenshot" content="screenshot.jpg" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>
<!-- Add a reference to the Azure Maps Services Module JavaScript file. -->
<script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>
<script>
var map, datasource, popup, searchURL, routeURL;
function getMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
//Use Microsoft Entra ID authentication.
authType: 'anonymous',
clientId: 'e6b6ab59-eb5d-4d25-aa57-581135b927f0', //Your Azure Maps client id for accessing your Azure Maps account.
getToken: function (resolve, reject, map) {
//URL to your authentication service that retrieves an Microsoft Entra ID Token.
var tokenServiceUrl = 'https://samples.azuremaps.com/api/GetAzureMapsToken';
fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
}
//Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
//authType: 'subscriptionKey',
//subscriptionKey: '[YOUR_AZURE_MAPS_KEY]'
}
});
//Use MapControlCredential to share authentication between a map control and the service module.
var pipeline = atlas.service.MapsURL.newPipeline(new atlas.service.MapControlCredential(map));
//Construct the RouteURL object
routeURL = new atlas.service.RouteURL(pipeline);
//Create an instance of the SearchURL client.
searchURL = new atlas.service.SearchURL(pipeline);
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Create a popup for displaying route section details.
popup = new atlas.Popup();
datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Create two line layers. One for the base route line, and another for the traffic sections on top. Render these below the labels.
map.layers.add(
//Render the base route line. This will look like an outline in areas that have traffic.
new atlas.layer.LineLayer(datasource, null, {
strokeWidth: 9,
lineJoin: 'round',
lineCap: 'round',
filter: ['!', ['has', 'magnitudeOfDelay']]
}), 'labels');
//Render the traffic section data above the route line.
var sectionLayer = new atlas.layer.LineLayer(datasource, null, {
//Use an expression to style the color based on the traffics magnitiude of delay metric: https://docs.microsoft.com/en-us/rest/api/maps/route/getroutedirections#magnitudeofdelay
strokeColor: [
'match',
['get', 'magnitudeOfDelay'],
3, 'red',
2, 'orange',
[
'match',
['get', 'simpleCategory'],
//If the category of the section is a Jam, make it orange.
'JAM', 'orange',
//If the category of the section is a road closure, make it black.
'ROAD_CLOSURE', 'black',
'GreenYellow'
]
],
strokeWidth: 7,
lineJoin: 'round',
lineCap: 'butt',
filter: ['has', 'magnitudeOfDelay']
});
//Add mouse events on the section layer so we can show a popup with details about the traffic issue.
map.events.add('mousemove', sectionLayer, showPopup);
map.events.add('touchstart', sectionLayer, showPopup);
//Close the popup on mouseout or touchend.
map.events.add('mouseout', sectionLayer, closePopup);
map.events.add('touchend', closePopup);
map.layers.add(sectionLayer, 'labels');
//Create a layer for rendering the start and end points of the route as symbols.
map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
iconOptions: {
image: ['get', 'iconImage'],
allowOverlap: true,
ignorePlacement: true
},
textOptions: {
textField: ['get', 'title'],
offset: [0, 1.2]
},
filter: ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']] //Only render Point or MultiPoints in this layer.
}));
//Calculate the initial route.
calculateRoute();
});
}
async function calculateRoute() {
datasource.clear();
var start = document.getElementById('startTbx').value;
var end = document.getElementById('endTbx').value;
if (start == '' || end == '') {
alert('Invalid waypoint point specified.');
return;
}
var geocodeOptions = {
limit: 1,
view: 'Auto'
};
//Geocode the start location.
var startResult = await searchURL.searchAddress(atlas.service.Aborter.timeout(3000), start, geocodeOptions);
if (startResult.results && startResult.results.length > 0) {
var startPoint = [startResult.results[0].position.lon, startResult.results[0].position.lat];
//Geocode the end location.
var endResult = await searchURL.searchAddress(atlas.service.Aborter.timeout(3000), end, geocodeOptions);
if (endResult.results && endResult.results.length > 0) {
var endPoint = [endResult.results[0].position.lon, endResult.results[0].position.lat];
//Calculate a route.
var directions = await routeURL.calculateRouteDirections(atlas.service.Aborter.timeout(10000), [startPoint, endPoint], {
sectionType: 'traffic', //Route option to return traffic sections.
maxAlternatives: 0
});
//Get the route data as GeoJSON and add it to the data source.
var data = directions.geojson.getFeatures();
var route = data.features[0];
datasource.add([route,
new atlas.data.Feature(new atlas.data.Point(startPoint), {
title: start,
iconImage: 'pin-blue'
}),
new atlas.data.Feature(new atlas.data.Point(endPoint), {
title: end,
iconImage: 'pin-red'
})
]);
//Extract the traffic section data.
if (route.properties.sections) {
var sections = route.properties.sections;
var sectionLines = [];
//Route path could be a MultiLineString as multiple route legs (specify 3 or more waypoints) can result in multiple lines.
var routePath = route.geometry.coordinates[0];
for (var i = 0; i < sections.length; i++) {
//Only worry about traffic sections with a magnitude delay of 1 (minor) or higher.
if (sections[i].sectionType === 'TRAFFIC' && sections[i].magnitudeOfDelay >= 1) {
//Create a line for the traffic section.
sectionLines.push(new atlas.data.Feature(new atlas.data.LineString(
//Get the coordinates from the route path for the section, startPointIndex...endPointIndex - add 1 as the end index is not included
routePath.slice(sections[i].startPointIndex, sections[i].endPointIndex + 1)
), sections[i]));
}
}
datasource.add(sectionLines);
}
//Update the map view to center over the route.
map.setCamera({
bounds: data.bbox,
padding: 30 //Add a padding to account for the pixel size of symbols.
});
} else {
alert('Unable to geocode end waypoint.');
}
} else {
alert('Unable to geocode start waypoint.');
}
}
function showPopup(e) {
//Make sure the event occurred on a shape feature.
if (e.shapes && e.shapes.length > 0) {
map.getCanvasContainer().style.cursor = 'pointer';
var properties = e.shapes[0].getProperties();
//Update the content and position of the popup.
popup.setOptions({
//Create the content of the popup.
content: `<div style="padding:10px;"><b>${properties.simpleCategory}</b><br/>Speed: ${Math.round(properties.effectiveSpeedInKmh * 0.62137119)} mph</div`,
position: e.position
});
//Open the popup.
popup.open(map);
}
}
function closePopup() {
popup.close();
map.getCanvasContainer().style.cursor = 'grab';
}
</script>
</head>
<body onload="getMap()">
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<div style="position:absolute;top:15px;left:15px;background-color:white;padding:10px;border-radius:10px;">
<table>
<tr>
<td>Start: </td>
<td><input type="text" id="startTbx" value="Seattle" /></td>
</tr>
<tr>
<td>End: </td>
<td><input type="text" id="endTbx" value="San Diego" /></td>
</tr>
<tr>
<td></td>
<td><input type="button" value="Calculate Route" onclick="calculateRoute()" /></td>
</tr>
</table>
</div>
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
<legend>Show traffic along route</legend>
This sample shows how to retrieve traffic information along a route using the <b>sectionType</b> option, and color the sections on the map.
</fieldset>
</body>
</html>