-
Notifications
You must be signed in to change notification settings - Fork 10
/
script.js
215 lines (197 loc) · 7.36 KB
/
script.js
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
var map;
var directionsService;
var marker = [];
var polyLine = [];
var poly2 = [];
var startLocation = [];
var endLocation = [];
var timerHandle = [];
var infoWindow = null;
var startLoc = [];
var endLoc = [];
var lastVertex = 1;
var step = 50; // 5; // metres
var eol = [];
window.initialize = initialize;
window.setRoutes = setRoutes;
// called on body load
function initialize() {
// initialize infoWindow
infoWindow = new google.maps.InfoWindow({
size: new google.maps.Size(150, 50)
});
var options = {
// max zoom
zoom: 18
};
map = new google.maps.Map(document.getElementById("map_canvas"), options);
//
// initial location which loads up on map
address = 'New Delhi'
// Geocoder is used to encode or actually geocode textual addresses to lat long values
geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function (results, status) {
map.fitBounds(results[0].geometry.viewport);
});
}
// returns the marker
function createMarker(latlng, label, html) {
var contentString = '<b>' + label + '</b><br>' + html;
// using Marker api, marker is created
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: label,
zIndex: 10
});
marker.myname = label;
// adding click listener to open up info window when marker is clicked
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(contentString);
infoWindow.open(map, marker);
});
return marker;
}
function toggleError(msg){
document.getElementById('error-msg').innerText = msg;
}
// Using Directions Service find the route between the starting and ending points
function setRoutes() {
map && initialize();
// empty out the error msg
toggleError("");
// set the values and check if any is empty, and if yes, show error and return
var startVal = document.getElementById("start").value
var endVal = document.getElementById("end").value;
if (!startVal || !endVal){
toggleError( "Please enter both start and end locations.");
return;
}
// just to avoid weird case of same start and end location
if (startVal === endVal){
toggleError( "Please enter different locations in both inputs");
return;
}
startLoc[0] = startVal;
endLoc[0] = endVal;
// empty out previous values
startLocation = [];
endLocation = [];
polyLine = [];
poly2 = [];
timerHandle = [];
var directionsDisplay = new Array();
for (var i = 0; i < startLoc.length; i++) {
var rendererOptions = {
map: map,
suppressMarkers: true,
preserveViewport: true
};
directionsService = new google.maps.DirectionsService();
var travelMode = google.maps.DirectionsTravelMode.DRIVING;
var request = {
origin: startLoc[i],
destination: endLoc[i],
travelMode: travelMode
};
directionsService.route(request, makeRouteCallback(i, directionsDisplay[i]), rendererOptions);
}
}
// called after getting route from directions service, does all the heavylifting
function makeRouteCallback(routeNum, disp, rendererOptions) {
// check if polyline and map exists, if yes, no need to do anything else, just start the animation
if (polyLine[routeNum] && (polyLine[routeNum].getMap() != null)) {
startAnimation(routeNum);
return;
}
return function (response, status) {
// if directions service successfully returns and no polylines exist already, then do the following
if (status == google.maps.DirectionsStatus.ZERO_RESULTS){
toggleError("No routes available for selected locations");
return;
}
if (status == google.maps.DirectionsStatus.OK) {
startLocation[routeNum] = new Object();
endLocation[routeNum] = new Object();
// set up polyline for current route
polyLine[routeNum] = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
poly2[routeNum] = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
// For each route, display summary information.
var legs = response.routes[0].legs;
// directionsrenderer renders the directions obtained previously by the directions service
disp = new google.maps.DirectionsRenderer(rendererOptions);
disp.setMap(map);
disp.setDirections(response);
// create Markers
for (i = 0; i < legs.length; i++) {
// for first marker only
if (i == 0) {
startLocation[routeNum].latlng = legs[i].start_location;
startLocation[routeNum].address = legs[i].start_address;
marker[routeNum] = createMarker(legs[i].start_location, "start", legs[i].start_address, "green");
}
endLocation[routeNum].latlng = legs[i].end_location;
endLocation[routeNum].address = legs[i].end_address;
var steps = legs[i].steps;
for (j = 0; j < steps.length; j++) {
var nextSegment = steps[j].path;
for (k = 0; k < nextSegment.length; k++) {
polyLine[routeNum].getPath().push(nextSegment[k]);
}
}
}
}
if (polyLine[routeNum]){
// render the line to map
polyLine[routeNum].setMap(map);
// and start animation
startAnimation(routeNum);
}
}
}
// Spawn a new polyLine every 20 vertices
function updatePoly(i, d) {
if (poly2[i].getPath().getLength() > 20) {
poly2[i] = new google.maps.Polyline([polyLine[i].getPath().getAt(lastVertex - 1)]);
}
if (polyLine[i].GetIndexAtDistance(d) < lastVertex + 2) {
if (poly2[i].getPath().getLength() > 1) {
poly2[i].getPath().removeAt(poly2[i].getPath().getLength() - 1)
}
poly2[i].getPath().insertAt(poly2[i].getPath().getLength(), polyLine[i].GetPointAtDistance(d));
} else {
poly2[i].getPath().insertAt(poly2[i].getPath().getLength(), endLocation[i].latlng);
}
}
// updates marker position to make the animation and update the polyline
function animate(index, d, tick) {
if (d > eol[index]) {
marker[index].setPosition(endLocation[index].latlng);
return;
}
var p = polyLine[index].GetPointAtDistance(d);
marker[index].setPosition(p);
updatePoly(index, d);
timerHandle[index] = setTimeout("animate(" + index + "," + (d + step) + ")", tick || 100);
}
// start marker movement by updating marker position every 100 milliseconds i.e. tick value
function startAnimation(index) {
if (timerHandle[index])
clearTimeout(timerHandle[index]);
eol[index] = polyLine[index].Distance();
map.setCenter(polyLine[index].getPath().getAt(0));
poly2[index] = new google.maps.Polyline({
path: [polyLine[index].getPath().getAt(0)],
strokeColor: "#FFFF00",
strokeWeight: 3
});
timerHandle[index] = setTimeout("animate(" + index + ",50)", 2000); // Allow time for the initial map display
}