How to show duration trip in google map api - google-maps

I'm using google map API to show the distance betewenn to points depending on the transportation and I like to show the duration of the trip like in the google map site (see the image). I'm using the v3 of google map and also the DirectionsRenderer function:
so far:
self.renderDirections = function (directions, status) {
self.cleanDisplayedDirections();
for (var i = 0, len = directions.routes.length; i < len && i < 3; i++) {
var direction = new google.maps.DirectionsRenderer({
map: map,
directions: directions,
routeIndex: i,
draggable: true,
suppressInfoWindows: false,
suppressMarkers: true
});
displayedDirections.push(direction);
}
};
Like in the image I would like to show, for instance, that is 13 min for the walk of 1 km.
Also, it is possible to change the polylineOptions for one route to be "dotted" like in the image?

EDIT: Okay, I have an answer to most of the components of your question.
(I kind of need this myself. I might as well write it now and post it here)
So I added a function that calculates a point, at a given distance, along a route. This is quite useful to place that infoWindow where you want it.
(probably a more elegant function could be written, but it does the trick)
You can take it from here, I guess. Just make var content as you need it to be. Add Walking/Driving image, ...
<!DOCTYPE html>
<html>
<head>
<title>How to show duration trip in google map api</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
html, body {
height: 90%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<input id="start" placeholder="start" value="Lausanne Gare">
<input id="end" placeholder="end" value="Chemin de Bellerive 32, 1007 Lausanne">
<input type="button" onclick="submit_form()" value="Calculate Route">
<script>
var directionsDisplayDriving;
var directionsDisplayWalking;
var infowindowDriving;
var infowindowWalking;
var directionsService;
var map;
// returns a polyline. Depending on the travelMode
function getPolylineOptions(travelMode) {
switch(travelMode) {
default:
case 'DRIVING':
return {
strokeColor: '#808080', // grey'ish
strokeOpacity: 1.0,
strokeWeight: 3
};
break;
case 'WALKING':
// Define a symbol using SVG path notation, with an opacity of 1.
var lineSymbol = {
path: 'M 0,-1 0,1',
strokeOpacity: 1,
scale: 3
};
// Create the polyline, passing the symbol in the 'icons' property.
// Give the line an opacity of 0.
// Repeat the symbol at intervals of 20 pixels to create the dashed effect.
return {
strokeColor: '#0099ff',
strokeOpacity: 0,
strokeWeight: 3,
icons: [{
icon: lineSymbol,
offset: '0',
repeat: '15px'
}]
};
break;
}
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 46.5138527, lng: 6.6260286}, // Lausanne
zoom: 12
});
directionsService = new google.maps.DirectionsService();
}
// reads the inputs and calculates the route
function submit_form() {
// remove previous routes
if(directionsDisplayDriving) {
directionsDisplayDriving.setMap(null);
directionsDisplayDriving = null;
}
if(directionsDisplayWalking) {
directionsDisplayWalking.setMap(null);
directionsDisplayWalking = null;
}
// calculate the route, both Driving and Walking
calcRoute(
document.getElementById('start').value,
document.getElementById('end').value,
'DRIVING',
function(display) {
// we put an infoWindow, 20% along the Driving route, and display the total length and duration in the content.
directionsDisplayDriving = display;
var point = distanceAlongPath(display, null, .2);
var content = 'Driving - total distance: ' + getTotalDistance(display) + 'm <br/> total duration: ' + getTotalDuration(display) +'s';
if(infowindowDriving) {
infowindowDriving.setMap(null);
}
infowindowDriving = new google.maps.InfoWindow({
content: content,
map: map,
position: point
});
}
);
calcRoute(
document.getElementById('start').value,
document.getElementById('end').value,
'WALKING',
function(display) {
// we put an infoWindow, 40% along the Walking route, and display the total length and duration in the content.
directionsDisplayWalking = display;
var point = distanceAlongPath(display, null, .4);
var content = 'Walking - total distance: ' + getTotalDistance(display) + 'm <br/> total duration: ' + getTotalDuration(display) +'s';
if(infowindowWalking) {
infowindowWalking.setMap(null);
}
infowindowWalking = new google.maps.InfoWindow({
content: content,
map: map,
position: point
});
}
);
////absolute (in meter)
//var point = distanceAlongPath(directionsDisplay, 100000);
// as a ratio (0 to 1) of the route
//var point = distanceAlongPath(directionsDisplay, null, 0.3); // at 30% from the origin
}
function calcRoute(start, end, travelMode, onReady) {
// alert(travelMode);
var mode = google.maps.TravelMode[travelMode];
var request = {
origin: start,
destination: end,
travelMode: mode
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var polylineOptions = getPolylineOptions(travelMode);
var directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true,
map: map,
polylineOptions: polylineOptions,
preserveViewport: false
});
directionsDisplay.setDirections(response);
if(typeof onReady == 'function') {
onReady(directionsDisplay);
}
}
else {
console.log('status: ' + status);
}
});
}
function getTotalDuration(directionsDisplay) {
var directionsResult = directionsDisplay.getDirections();
var route = directionsResult.routes[0];
var totalDuration = 0;
var legs = route.legs;
for(var i=0; i<legs.length; ++i) {
totalDuration += legs[i].duration.value;
}
return totalDuration;
}
function getTotalDistance(directionsDisplay) {
var directionsResult = directionsDisplay.getDirections();
var route = directionsResult.routes[0];
var totalDistance = 0;
var legs = route.legs;
for(var i=0; i<legs.length; ++i) {
totalDistance += legs[i].distance.value;
}
return totalDistance;
}
// Returns a point along a route; at a requested distance ( either absolute (in meter) or as a ratio (0 to 1) of the route)
// example : you have a random route ( 100km long), and you want to put a marker, 30km from the origin.
// we add the distances of the waypoints and stop when we reach the requested total length.
// nothing stops you from making it even more precise by interpolling.
// the function returns a location (LatLng) along the route
function distanceAlongPath(directionsDisplay, distanceFromOrigin, ratioFromOrigin) {
var directionsResult = directionsDisplay.getDirections();
var route = directionsResult.routes[0];
var totalDistance = getTotalDistance(directionsDisplay);
var tempDistanceSum = 0;
var dist = 0;
if(ratioFromOrigin) {
distanceFromOrigin = ratioFromOrigin * totalDistance;
}
// we prepare the object
var result = new Object();
result.routes = new Array();
result.routes[0] = route;
for(var i in result.routes[0].overview_path) {
if (i>0) {
dist = google.maps.geometry.spherical.computeDistanceBetween (result.routes[0].overview_path[i], result.routes[0].overview_path[i - 1]);
}
tempDistanceSum += dist;
if (tempDistanceSum > distanceFromOrigin) {
return result.routes[0].overview_path[i];
}
// console.log(dist+' '+tempDistanceSum);
}
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry" async defer></script>
</body>
</html>
(FIRST submitted, might be interesting for the details of the dashed polylines)
Also, it is possible to change the polylineOptions for one route to be "dotted" like in the image?
Here is part of your question.
A Select box has
DRIVING: with a normal polyline (I gave it some color)
WALKING: with a dashed polyline. I suppose you should try out different numbers, to get the lineType right.
<!DOCTYPE html>
<html>
<head>
<title>Google Maps - Dashed polylines</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
html, body {
height: 90%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<input id="start" placeholder="start" value="Brussels">
<input id="end" placeholder="end" value="Paris">
<select id="mode">
<option value="DRIVING">DRIVING</option>
<option value="WALKING">WALKING</option>
</select>
<input type="button" onclick="submit_form()" value="Calculate Route">
<script>
var directionsDisplay;
var directionsService;
var map;
// returns a polyline. Depending on the travelMode
function getPolylineOptions(travelMode) {
// alert(travelMode);
switch(travelMode) {
default:
case 'DRIVING':
return {
strokeColor: '#808080', // grey'ish
strokeOpacity: 1.0,
strokeWeight: 3
};
break;
case 'WALKING':
// Define a symbol using SVG path notation, with an opacity of 1.
var lineSymbol = {
path: 'M 0,-1 0,1',
strokeOpacity: 1,
scale: 4
};
// Create the polyline, passing the symbol in the 'icons' property.
// Give the line an opacity of 0.
// Repeat the symbol at intervals of 20 pixels to create the dashed effect.
return {
strokeColor: '#ff0000', // red
strokeOpacity: 0,
//strokeWeight: 3,
icons: [{
icon: lineSymbol,
offset: '0',
repeat: '20px'
}]
};
break;
}
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 50.869754630095834, lng: 4.353812903165801}, // Brussels
zoom: 12
});
directionsService = new google.maps.DirectionsService();
}
// reads the inputs and calculates the route
function submit_form() {
calcRoute(
document.getElementById('start').value,
document.getElementById('end').value,
document.getElementById('mode').value
)
}
function calcRoute(start, end, travelMode) {
// alert(travelMode);
var mode = google.maps.TravelMode[travelMode];
var request = {
origin: start,
destination: end,
travelMode: mode
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var polylineOptions = getPolylineOptions(travelMode);
// you might want to remove the previous polyline. If not, don't add this
if(directionsDisplay) {
directionsDisplay.setMap(null);
}
directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true,
map: map,
polylineOptions: polylineOptions,
preserveViewport: false
});
directionsDisplay.setDirections(response);
}
else {
console.log('status: ' + status);
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap" async defer></script>
</body>
</html>

Related

How to make the polyline change with the draggable route [duplicate]

This question already has answers here:
How to get a draggable waypoint's location from google directions result
(1 answer)
Google Maps API v3 - Directions with draggable alternate routes
(1 answer)
suppressMarkers and draggable for DirectionsRendererOptions Google Maps API
(1 answer)
How do I change the route provided to me by the directions API on web?
(1 answer)
Closed last month.
I am trying to create a polyline from the route. The route is draggable and it has waypoints. I am using the directions_changed event listener to draw the polyline so that whenever the route changes the polyline also changes. I am able to achieve all of this except then when I drag the route I get the new polyline but I also have the older polyline drawn on the route. Whenever the route is dragged I don't want the older polyline to appear along with the new polyline.
How can I achieve this?
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: { lat: -24.345, lng: 134.46 }, // Australia.
});
const directionsService = new google.maps.DirectionsService();
const directionsRenderer = new google.maps.DirectionsRenderer({
draggable: true,
map,
panel: document.getElementById("panel"),
});
directionsRenderer.addListener("directions_changed", () => {
const directions = directionsRenderer.getDirections();
if (directions) {
computeTotalDistance(directions);
var polyline = new google.maps.Polyline(
{
path:google.maps.geometry.encoding.decodePath(directions.routes[0].overview_polyline),
map : map
}
)
if(polyline)
{
console.log(polyline)
polyline.setMap(map)
}
}
});
displayRoute(
"Perth, WA",
"Sydney, NSW",
directionsService,
directionsRenderer
);
}
function displayRoute(origin, destination, service, display) {
service
.route({
origin: origin,
destination: destination,
waypoints: [
{ location: "Adelaide, SA" },
{ location: "Broken Hill, NSW" },
],
travelMode: google.maps.TravelMode.DRIVING,
avoidTolls: true,
})
.then((result) => {
display.setDirections(result);
})
.catch((e) => {
alert("Could not display directions due to: " + e);
});
}
function computeTotalDistance(result) {
let total = 0;
const myroute = result.routes[0];
if (!myroute) {
return;
}
for (let i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById("total").innerHTML = total + " km";
}
window.initMap = initMap;
If you want to hide the old polyline, keep a reference to it (outside the scope of the directions_changed listener) and remove it from the map with polyline.setMap(null); before creating the new polyline:
if (polyline) {
// if polyline already exists, remove it from the map.
polyline.setMap(null)
}
polyline = new google.maps.Polyline({
path: google.maps.geometry.encoding.decodePath(directions.routes[0].overview_polyline),
map: map
})
proof of concept fiddle
code snippet:
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: {
lat: -24.345,
lng: 134.46
}, // Australia.
});
const directionsService = new google.maps.DirectionsService();
const directionsRenderer = new google.maps.DirectionsRenderer({
draggable: true,
map,
panel: document.getElementById("panel"),
});
let polyline;
directionsRenderer.addListener("directions_changed", () => {
const directions = directionsRenderer.getDirections();
if (directions) {
computeTotalDistance(directions);
if (polyline) {
// if polyline already exists, remove it from the map.
polyline.setMap(null)
}
polyline = new google.maps.Polyline({
path: google.maps.geometry.encoding.decodePath(directions.routes[0].overview_polyline),
map: map
})
if (polyline) {
console.log(polyline)
polyline.setMap(map)
}
}
});
displayRoute(
"Perth, WA",
"Sydney, NSW",
directionsService,
directionsRenderer
);
}
function displayRoute(origin, destination, service, display) {
service
.route({
origin: origin,
destination: destination,
waypoints: [{
location: "Adelaide, SA"
},
{
location: "Broken Hill, NSW"
},
],
travelMode: google.maps.TravelMode.DRIVING,
avoidTolls: true,
})
.then((result) => {
display.setDirections(result);
})
.catch((e) => {
alert("Could not display directions due to: " + e);
});
}
function computeTotalDistance(result) {
let total = 0;
const myroute = result.routes[0];
if (!myroute) {
return;
}
for (let i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById("total").innerHTML = total + " km";
}
window.initMap = initMap;
/*
* Always set the map height explicitly to define the size of the div element
* that contains the map.
*/
#map {
height: 90%;
}
/*
* Optional: Makes the sample page fill the window.
*/
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: "Roboto", "sans-serif";
line-height: 30px;
padding-left: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>Directions Service</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="total"></div>
<div id="map"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/#googlemaps/js-api-loader.
-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=weekly" defer></script>
</body>
</html>

How to assign info window in polyline using google map api

My Scenario. I have five markers and connecting to the polyline. When I click marker a to marker b between polyline it will show an info window. In the info, the window has marker a address and marker b address. I achieved this scenario using islocationedge concept in google Maps API. but this concept I facing an issue. when I click marker a to marker b polyline it will show marker b and marker c address because segment polyline I used. I need how to assign an info window in an individual polyline.
My code
<!DOCTYPE html>
<html>
<body>
<h1>My First Google Map</h1>
<div id="googleMap" style="width:100%;height:400px;"></div>
<script>
function myMap() {
var mapProp= {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
var goldenGatePosition = [{lat: 30.2179130,lng: -81.5628150, address: 'Tamil Nadu'},{lat: 30.2179140,lng: -81.5627480, address: 'India'},{lat:30.2177650,lng:-81.5629100,address: 'America'},{lat: 30.2844080,lng: -81.5633900, address: 'Tamil Nadu'},{lat: 30.2843840,lng: -81.5633890, address: 'Tamil Nadu'}];
for(let i=0;i<goldenGatePosition.length;i++){
var marker = new google.maps.Marker({
position: goldenGatePosition[i],
map: map,
title: 'Golden Gate Bridge'
});
}
var flightPath = new google.maps.Polyline({
path:goldenGatePosition,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2
});
flightPath.setMap(map);
let poly, geodesicPoly;
var infowindow = new google.maps.InfoWindow();
var codeStr=''
google.maps.event.addListener(flightPath, 'click', function(event) {
// make polyline for each segment of the input line
for (var i = 0; i < this.getPath().getLength() - 1; i++) {
var segmentPolyline = new google.maps.Polyline({
path: [this.getPath().getAt(i), this.getPath().getAt(i + 1)]
});
console.log(segmentPolyline)
// check to see if the clicked point is along that segment
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline, 10e-3)) {
console.log(' I ', i)
// output the segment number and endpoints in the InfoWindow
var origin = new Array()
var destination = new Array()
console.log('****************')
for(let i=0;i<goldenGatePosition.length; i++){
console.log(goldenGatePosition[i])
}
console.log('****************')
console.log(segmentPolyline.getPath().getAt(0).address)
origin.push(segmentPolyline.getPath().getAt(0).toUrlValue(6))
destination.push(segmentPolyline.getPath().getAt(1).toUrlValue(6))
const service = new google.maps.DistanceMatrixService(); // instantiate Distance Matrix service
const matrixOptions = {
origins: origin, // technician locations
destinations: destination, // customer address
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.IMPERIAL
};
// Call Distance Matrix service
service.getDistanceMatrix(matrixOptions, callback);
// Callback function used to process Distance Matrix response
function callback(response, status) {
console.log(response)
console.log(status)
if (status !== "OK") {
alert("Error with distance matrix");
return;
}
console.log(response);
}
var content = "segment " + i + "<br>";
content += "start of segment=" + segmentPolyline.getPath().getAt(0).toUrlValue(6) + "<br>";
content += "end of segment=" + segmentPolyline.getPath().getAt(1).toUrlValue(6) + "<br>";
infowindow.setContent(content);
infowindow.setPosition(event.latLng);
infowindow.open(map);
}
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAiybKuHI544-t5XPZzBGjQOBCO4MZFCwM&callback=myMap&libraries=geometry"></script>
</body>
</html>
When i click the polyline. How to get marker coordinates from polyline one end to another end.
The tolerance in your call to isLocationOnEdge is too small.
isLocationOnEdge
isLocationOnEdge(point, poly[, tolerance])
Parameters:
point: LatLng
poly: Polygon|Polyline
tolerance: number optional
Return Value:* boolean
Computes whether the given point lies on or near to a polyline, or the edge of a polygon, within a specified tolerance. Returns true when the difference between the latitude and longitude of the supplied point, and the closest point on the edge, is less than the tolerance. The tolerance defaults to 10-9 degrees.
Your code:
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline, 10e-3)) {
Working value:
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline, 10e-7)) {
(when it is too large, it is picking up segment 1 for all locations on segment 0, as far as I can tell, all the other segments work correctly with your value)
proof of concept fiddle
code snippet:
function myMap() {
var mapProp = {
center: new google.maps.LatLng(51.508742, -0.120850),
zoom: 5,
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var bounds = new google.maps.LatLngBounds();
for (let i = 0; i < goldenGatePosition.length; i++) {
var marker = new google.maps.Marker({
position: goldenGatePosition[i],
map: map,
title: goldenGatePosition[i].address
});
if (i == 0 || i == 1) bounds.extend(marker.getPosition());
}
map.fitBounds(bounds);
var flightPath = new google.maps.Polyline({
path: goldenGatePosition,
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2
});
flightPath.setMap(map);
let poly, geodesicPoly;
var infowindow = new google.maps.InfoWindow();
var codeStr = ''
google.maps.event.addListener(flightPath, 'click', function(event) {
// make polyline for each segment of the input line
for (var i = 0; i < this.getPath().getLength() - 1; i++) {
var segmentPolyline = new google.maps.Polyline({
path: [this.getPath().getAt(i), this.getPath().getAt(i + 1)]
});
console.log(segmentPolyline)
// check to see if the clicked point is along that segment
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline, 10e-7)) {
console.log(' I ', i)
// output the segment number and endpoints in the InfoWindow
var origin = new Array()
var destination = new Array()
console.log('****************')
for (let i = 0; i < goldenGatePosition.length; i++) {
console.log(goldenGatePosition[i])
}
console.log('****************')
console.log(segmentPolyline.getPath().getAt(0).address)
origin.push(segmentPolyline.getPath().getAt(0).toUrlValue(6))
destination.push(segmentPolyline.getPath().getAt(1).toUrlValue(6))
const service = new google.maps.DistanceMatrixService(); // instantiate Distance Matrix service
const matrixOptions = {
origins: origin, // technician locations
destinations: destination, // customer address
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.IMPERIAL
};
// Call Distance Matrix service
service.getDistanceMatrix(matrixOptions, callback);
console.log("break")
// Callback function used to process Distance Matrix response
function callback(response, status) {
console.log(response)
console.log(status)
if (status !== "OK") {
alert("Error with distance matrix");
return;
}
console.log(response);
}
var content = "segment " + i + "<br>";
content += "start of segment=" + segmentPolyline.getPath().getAt(0).toUrlValue(6) + "<br>";
content += "end of segment=" + segmentPolyline.getPath().getAt(1).toUrlValue(6) + "<br>";
infowindow.setContent(content);
infowindow.setPosition(event.latLng);
infowindow.open(map);
}
}
});
}
var goldenGatePosition = [{
lat: 30.2179130,
lng: -81.5628150,
address: 'Tamil Nadu'
}, {
lat: 30.2179140,
lng: -81.5627480,
address: 'India'
}, {
lat: 30.2177650,
lng: -81.5629100,
address: 'America'
}, {
lat: 30.2844080,
lng: -81.5633900,
address: 'Tamil Nadu'
}, {
lat: 30.2843840,
lng: -81.5633890,
address: 'Tamil Nadu'
}];
html,
body,
#googleMap {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
<div id="googleMap"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=myMap&libraries=geometry" defer></script>

How to get coordinates in polyline using google map?

I tried to create a polyline in google Maps. It's created and polyline also working fine. but I need when to click polyline to get coordinates. My Scenario(I have three markers in google map.so, three markers used to connect the polyline markerA connect to markerB connect to markerC. when I click polyline in between markerA and makrerB. I need that two markers latitude and longitude). How to achieve this scenario.
My Code
<!DOCTYPE html>
<html>
<body>
<h1>My First Google Map</h1>
<div id="googleMap" style="width:100%;height:400px;"></div>
<script>
function myMap() {
var mapProp= {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
var goldenGatePosition = [{lat: 11.0168,lng: 76.9558},{lat: 11.6643,lng: 78.1460},{lat:11.2189,lng:78.1674}];
for(let i=0;i<goldenGatePosition.length;i++){
var marker = new google.maps.Marker({
position: goldenGatePosition[i],
map: map,
title: 'Golden Gate Bridge'
});
}
var flightPath = new google.maps.Polyline({
path:goldenGatePosition,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2
});
flightPath.setMap(map);
var infowindow = new google.maps.InfoWindow();
var codeStr=''
google.maps.event.addListener(flightPath, 'click', function(event) {
infowindow.setContent("content");
// var pathArr = flightPath.getPath()
// for (var i = 0; i < pathArr.length; i++){
// codeStr = '{lat: ' + pathArr.getAt(i).lat() + ', lng: ' + pathArr.getAt(i).lng() + '}' ;
// console.log(codeStr)
// };
console.log(event.latLng)
var length = this.getLength();
var mid = Math.round( length / 2 );
var pos = this.getAt( mid );
console.log(pos)
// infowindow.position = event.latLng;
infowindow.setPosition(event.latLng);
infowindow.open(map);
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCHmYOxkvd4u3rbHqalUSlGOa-b173lygA&callback=myMap"></script>
</body>
</html>
Google Map
Simplest way:
include the google maps geometry library.
use the poly namespace isLocationOnEdge method to detect which segment of the polyline the click was on. Output the two end coordinates of that segment.
isLocationOnEdge(point, poly[, tolerance])
Parameters:
point: LatLng
poly: Polygon|Polyline
tolerance: number optional
Return Value: boolean
Computes whether the given point lies on or near to a polyline, or the edge of a polygon, within a specified tolerance. Returns true when the difference between the latitude and longitude of the supplied point, and the closest point on the edge, is less than the tolerance. The tolerance defaults to 10-9 degrees.
google.maps.event.addListener(flightPath, 'click', function(event) {
// make polyline for each segment of the input line
for (var i = 0; i < this.getPath().getLength() - 1; i++) {
var segmentPolyline = new google.maps.Polyline({
path: [this.getPath().getAt(i), this.getPath().getAt(i + 1)]
});
// check to see if the clicked point is along that segment
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline,10e-3)) {
// output the segment number and endpoints in the InfoWindow
var content = "segment "+i+"<br>";
content += "start of segment=" + segmentPolyline.getPath().getAt(0).toUrlValue(6) + "<br>";
content += "end of segment=" + segmentPolyline.getPath().getAt(1).toUrlValue(6) + "<br>";
infowindow.setContent(content);
infowindow.setPosition(event.latLng);
infowindow.open(map);
}
}
});
proof of concept fiddle
code snippet:
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#googleMap {
height: 80%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<h1>My First Google Map</h1>
<div id="googleMap"></div>
<script>
function myMap() {
var mapProp = {
center: new google.maps.LatLng(51.508742, -0.120850),
zoom: 5,
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var goldenGatePosition = [{
lat: 11.0168,
lng: 76.9558
}, {
lat: 11.6643,
lng: 78.1460
}, {
lat: 11.2189,
lng: 78.1674
}];
var bounds = new google.maps.LatLngBounds();
for (let i = 0; i < goldenGatePosition.length; i++) {
var marker = new google.maps.Marker({
position: goldenGatePosition[i],
map: map,
title: 'Golden Gate Bridge'
});
bounds.extend(goldenGatePosition[i]);
}
var flightPath = new google.maps.Polyline({
path: goldenGatePosition,
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2
});
flightPath.setMap(map);
map.fitBounds(bounds);
var infowindow = new google.maps.InfoWindow();
var codeStr = ''
google.maps.event.addListener(flightPath, 'click', function(event) {
// make polyline for each segment of the input line
for (var i = 0; i < this.getPath().getLength() - 1; i++) {
var segmentPolyline = new google.maps.Polyline({
path: [this.getPath().getAt(i), this.getPath().getAt(i + 1)]
});
// check to see if the clicked point is along that segment
if (google.maps.geometry.poly.isLocationOnEdge(event.latLng, segmentPolyline, 10e-3)) {
// output the segment number and endpoints in the InfoWindow
var content = "segment " + i + "<br>";
content += "start of segment=" + segmentPolyline.getPath().getAt(0).toUrlValue(6) + "<br>";
content += "end of segment=" + segmentPolyline.getPath().getAt(1).toUrlValue(6) + "<br>";
infowindow.setContent(content);
infowindow.setPosition(event.latLng);
infowindow.open(map);
}
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=myMap"></script>

Display multiple routes on google map

I am trying to show multiple routes on google map but It is showing only one. Can you please what I am doing wrong?
<div class="searchmap" style="float:left;margin-left:1%" id="map"></div>
var map = null;
var markerPoints = [];
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
function initialize()
{
directionsDisplay = new google.maps.DirectionsRenderer();
map = new google.maps.Map(document.getElementById("map"), {scrollwheel:false, mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: false, streetViewControl: false, center:new google.maps.LatLng(19.0759837, 72.87765590000004), zoom:13});
directionsDisplay.setMap(map);
}
function calcRoute(flat, flng, tlat, tlng)
{
var start = new google.maps.LatLng(flat, flng);
var end = new google.maps.LatLng(tlat, tlng);
var request = {
origin:start,
destination:end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: false,
suppressInfoWindows: true
});
directionsDisplay.setMap(map);
directionsService.route(request, function(result, status) {
console.log(result);
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
calcRoute("19.210430", "72.843422", "19.109858", "72.878433");
calcRoute("19.228977", "72.856812", "19.117302", "72.884041");
Can you please let me know what I am doing wrong?
Display multiple routes on google map with waypoints and direction arrow
==============
Click here!
![In image u can see 2 routes with direction arrow][1]
<style>
html, body, #map_canvas { margin: 0; padding: 0; height: 100% }
</style>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script>
var directionsService;
var stepDisplay;
var position;
var marker = [];
var polyline = [];
var poly2 = [];
var poly = null;
var startLocation = [];
var endLocation = [];
var timerHandle = [];
var stops_data = [[ {"Geometry":{"Latitude":23.05242,"Longitude":72.53375}},
{"Geometry":{"Latitude":23.03007,"Longitude":72.59664}}
] ,[ {"Geometry":{"Latitude":23.00959,"Longitude":72.56189}},
{"Geometry":{"Latitude":23.05754,"Longitude":72.55302}}
]];
var a,z,b;
var add;
var speed = 0.000005, wait = 1;
var infowindow = null;
infowindow = new google.maps.InfoWindow();
var myPano;
var panoClient;
var nextPanoId;
var directionsDisplay = [];
directionsDisplay[0] = new window.google.maps.DirectionsRenderer({
suppressMarkers: true
});
directionsDisplay[1] = new window.google.maps.DirectionsRenderer({
suppressMarkers: true
});
var map;
var mapOptions = { center: new google.maps.LatLng(42.5584308, -70.8597732), zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP };
function initialize()
{
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsService = new google.maps.DirectionsService();
// Setroute(locations[0],locations[1],directionsDisplay[0]);
// Setroute(locations2[0],locations2[1],directionsDisplay[1]);
Tour_startUp(stops_data[0]);
window.tour.loadMap(map, directionsDisplay[0]);
window.tour.fitBounds(stops_data[0],map);
if (stops_data[0].length > 1)
window.tour.calcRoute(stops_data[0],directionsService, directionsDisplay[0]);
Tour_startUp(stops_data[1]);
window.tour.loadMap(map, directionsDisplay[1]);
window.tour.calcRoute(stops_data[1],directionsService, directionsDisplay[1]);
window.tour.fitBounds(stops_data[1],map);
}
function fx(o)
{
if(o && o.legs)
{
for(l=0;l<o.legs.length;l++)
{
var leg=o.legs[l];
for(var s=0;s<leg.steps.length;++s)
{
var step=leg.steps[s],
a=(step.lat_lngs.length)?step.lat_lngs[0]:step.start_point,
z=(step.lat_lngs.length)?step.lat_lngs[1]:step.end_point,
dir=((Math.atan2(z.lng()-a.lng(),z.lat()-a.lat())*180)/Math.PI)+360,
ico=((dir-(dir%3))%120);
new google.maps.Marker({
position: a,
icon: new google.maps.MarkerImage('http://maps.google.com/mapfiles/dir_'+ico+'.png',
new google.maps.Size(24,24),
new google.maps.Point(0,0),
new google.maps.Point(12,12)
),
map: map,
title: Math.round((dir>360)?dir-360:dir)+'°'
});
}
}
}
}
function Tour_startUp(stops) {
// alert('first'+stops.length);
if (!window.tour) window.tour = {
updateStops: function (newStops) {
stops = newStops;
},
// map: google map object
// directionsDisplay: google directionsDisplay object (comes in empty)
loadMap: function (map, dirdis) {
var myOptions = {
zoom: 15,
center: new window.google.maps.LatLng(51.507937, -0.076188), // default to London
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
map.setOptions(myOptions);
dirdis.setMap(map);
},
fitBounds: function (stops_data,map) {
var bounds = new window.google.maps.LatLngBounds();
// extend bounds for each record
for( var x in stops_data) {
var myLatlng = new window.google.maps.LatLng(stops_data[x].Geometry.Latitude, stops_data[x].Geometry.Longitude);
bounds.extend(myLatlng);
}
map.fitBounds(bounds);
},
calcRoute: function (stops_new,directionsService, dirdis) {
var batches = [];
var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
var itemsCounter = 0;
var wayptsExist = stops_new.length > 0;
var time= [];
while (wayptsExist) {
var subBatch = [];
var subitemsCounter = 0;
// alert('second'+stops_new.length);
//alert(stops_new[0].Geometry.Latitude +' ===== ' +stops_new[0].Geometry.Longitude);
for (var j = itemsCounter; j < stops_new.length; j++) {
subitemsCounter++;
//alert(stops[j].Geometry.Time);
subBatch.push({
location: new window.google.maps.LatLng(stops_new[j].Geometry.Latitude, stops_new[j].Geometry.Longitude),
stopover: true
});
//time.push(stops[j].Geometry.Time);
if (subitemsCounter == itemsPerBatch)
break;
}
itemsCounter += subitemsCounter;
batches.push(subBatch);
wayptsExist = itemsCounter < stops_new.length;
// If it runs again there are still points. Minus 1 before continuing to
// start up with end of previous tour leg
itemsCounter--;
}
// now we should have a 2 dimensional array with a list of a list of waypoints
var combinedResults;
var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
var directionsResultsReturned = 0;
for (var k = 0; k < batches.length; k++) {
var lastIndex = batches[k].length - 1;
var start = batches[k][0].location;
var end = batches[k][lastIndex].location;
// trim first and last entry from array
var waypts = [];
waypts = batches[k];
waypts.splice(0, 1);
waypts.splice(waypts.length - 1, 1);
var request =
{
origin: start,
destination: end,
waypoints: waypts,
travelMode: window.google.maps.TravelMode.WALKING
};
// alert('start'+start);
// alert('end'+end);
(function (kk) {
directionsService.route(request, function (result, status) {
if (status == window.google.maps.DirectionsStatus.OK) {
fx(result.routes[0]);
polyline[0] = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
poly2[0] = new google.maps.Polyline({
path: [],
strokeColor: '#FFFF00',
strokeWeight: 3
});
var unsortedResult = { order: kk, result: result };
unsortedResults.push(unsortedResult);
directionsResultsReturned++;
if (directionsResultsReturned == batches.length) // we've received all the results. put to map
{
// sort the returned values into their correct order
unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
var count = 0;
for (var key in unsortedResults) {
if (unsortedResults[key].result != null) {
if (unsortedResults.hasOwnProperty(key)) {
if (count == 0) // first results. new up the combinedResults object
combinedResults = unsortedResults[key].result;
else {
// only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
// directionResults object, but enough to draw a path on the map, which is all I need
combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
}
count++;
}
}
}
dirdis.setDirections(combinedResults);
var legs = combinedResults.routes[0].legs;
var path = combinedResults.routes[0].overview_path;
//alert(path.length);
// alert(legs.length);
//setRoutes(legs[0].start_location,legs[legs.length-1].end_location);
for (var i=0; i < legs.length;i++)
{
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
if (i == 0) {
//marker[0] = createMarker2(legs[i].start_location,"start",legs[i].start_address,"green");
}
var steps = legs[i].steps;
// alert('arrival time : '+legs[i].arrival_time.text);
// var duration = steps.duration_in_traffic;
// alert(duration.text);
for (j=0;j<steps.length;j++)
{
var nextSegment = steps[j].path;
for (k=0;k<nextSegment.length;k++)
{
polyline[0].getPath().push(nextSegment[k]);
//bounds.extend(nextSegment[k]);
}
}
// createMarker(directionsDisplay.getMap(),legs[i].start_location,"marker"+i,"some text for marker "+i+"<br>"+legs[i].start_address,markerletter);
}
// Marker for start point
createMarker(dirdis.getMap(),legs[0].start_location,"marker"+0,"Start Point<br>"+legs[0].start_address,'A');
var i=legs.length;
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
// marker for End Point
createMarker(dirdis.getMap(),legs[legs.length-1].end_location,"marker"+i,"End Point <br>"+legs[legs.length-1].end_address,'B');
polyline[0].setMap(map);
//startAnimation(0);
}
}
});
})(k);
}
}
};
}
var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
function getMarkerImage(iconStr) {
//alert(iconStr);
if ((typeof(iconStr)=="undefined") || (iconStr==null)) {
iconStr = "red";
}
if(iconStr == 'A')
{
// for start point
if (!icons[iconStr]) {
icons[iconStr] = new google.maps.MarkerImage("http://www.google.com/mapfiles/dd-start.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 6,20.
new google.maps.Point(9, 34));
}
}
if (iconStr == 'B')
{
// for end point
if (!icons[iconStr]) {
icons[iconStr] = new google.maps.MarkerImage("http://www.google.com/mapfiles/dd-end.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 6,20.
new google.maps.Point(9, 34));
}
}
return icons[iconStr];
}
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
new google.maps.Size(37, 34),
new google.maps.Point(0,0),
new google.maps.Point(9, 34));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var iconShape = {
coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
type: 'poly'
};
function createMarker(map, latlng, label, html, color) {
//alert(color);
// alert("createMarker("+latlng+","+label+","+html+","+color+")");
var contentString = '<b>'+label+'</b><br>'+html;
// alert('creatMarker'+contentString);
var marker = new google.maps.Marker({
position: latlng,
map: map,
shadow: iconShadow,
icon: getMarkerImage(color),
shape: iconShape,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<div id="map_canvas"></div>
[1]: http://i.stack.imgur.com/yB4Tw.png
Here you go.. the full explaination , credit goes to the author
function drawMap() {
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var start = new google.maps.LatLng(51.47482547819850,-0.37739553384529);
var myOptions = {
zoom:7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: start
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
function renderDirections(result) {
var directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map);
directionsRenderer.setDirections(result);
}
function requestDirections(start, end) {
directionsService.route({
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(result) {
renderDirections(result);
});
}
requestDirections('(51.47482547819850,-0.37739553384529)', '(51.59512428598160,-0.17190814889409)');
requestDirections('EC1V 0AH', '(51.47615506206120, -0.37795315370703)');
}
you need to create an instance of google.maps.DirectionsRenderer(); EVERYTIME you draw the route to make it visible ;)
Your directionsDisplay variable is an instance of google.maps.DirectionsRenderer() and that can only hold one set of directions at a time. If you want to display more than one route, you need multiple google.maps.DirectionsRenderer().
To get multiple routes we can add provideRouteAlternatives = true inside request object while calling route() of DirectionsService object. See Directions Requests.
This method will return array of routes if available with their name in summary key.
Now we can display these routes on view and on click of each route we can pass route object and can render the direction by setDirections() of DirectionsRenderer object. See Displaying the DirectionsResult
try this code
<!DOCTYPE html>
<html>
<head>
<title>Waypoints in Directions</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script
src="https://maps.googleapis.com/maps/api/js?key=your-key&callback=initMap&libraries=&v=weekly"
defer
></script>
<style type="text/css">
html,
body {
height: 99%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
float: left;
width: 99%;
height: 100%;
}
</style>
<script>
"use strict";
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 6,
center: {
lat: 19.8762,
lng: 75.3433
}
});
const directionsService = new google.maps.DirectionsService();
let points = [
{
origin: {
lat: 19.9974533,
lng: 73.78980229999999
},
destination: {
lat: 19.0759837,
lng: 72.8776559
},
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
},
{
origin: {
lat: 21.1458,
lng: 79.0882
},
destination: {
lat: 18.5204,
lng: 73.8567
},
// waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
}
]
for (var i = 0; i < points.length; i++) {
calculateAndDisplayRoute(directionsService,points[i])
}
function calculateAndDisplayRoute(directionsService,points) {
let directionsRenderer = new google.maps.DirectionsRenderer();
// const waypts = [{
// location: {
// lat: 19.8762,
// lng: 75.3433
// },
// },
// ];
directionsService.route(
points,
(response, status) => {
console.log(response);
if (status === "OK") {
directionsRenderer.setDirections(response);
directionsRenderer.setMap(map);
} else {
window.alert("Directions request failed due to " + status);
}
}
);
}
}
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

Google Maps V3 - waypoints + infowindow with random text

I'm using this example to set up a route with more then 8 markers.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Google Maps JavaScript API v3 Example: Directions Waypoints</title>
<style>
#map{
width: 100%;
height: 450px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script>
jQuery(function() {
var stops = [
{"Geometry":{"Latitude":52.1615470947258,"Longitude":20.80514430999756}},
{"Geometry":{"Latitude":52.15991486090931,"Longitude":20.804049968719482}},
{"Geometry":{"Latitude":52.15772967999426,"Longitude":20.805788040161133}},
{"Geometry":{"Latitude":52.15586034371232,"Longitude":20.80460786819458}},
{"Geometry":{"Latitude":52.15923693975469,"Longitude":20.80113172531128}},
{"Geometry":{"Latitude":52.159849043774074, "Longitude":20.791990756988525}},
{"Geometry":{"Latitude":52.15986220720892,"Longitude":20.790467262268066}},
{"Geometry":{"Latitude":52.16202095784738,"Longitude":20.7806396484375}},
{"Geometry":{"Latitude":52.16088894313116,"Longitude":20.77737808227539}},
{"Geometry":{"Latitude":52.15255590234335,"Longitude":20.784244537353516}},
{"Geometry":{"Latitude":52.14747369312591,"Longitude":20.791218280792236}},
{"Geometry":{"Latitude":52.14963304460396,"Longitude":20.79387903213501}}
] ;
var map = new window.google.maps.Map(document.getElementById("map"));
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer();
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
window.tour.fitBounds(map);
if (stops.length > 1)
window.tour.calcRoute(directionsService, directionsDisplay);
});
function Tour_startUp(stops) {
if (!window.tour) window.tour = {
updateStops: function (newStops) {
stops = newStops;
},
// map: google map object
// directionsDisplay: google directionsDisplay object (comes in empty)
loadMap: function (map, directionsDisplay) {
var myOptions = {
zoom: 13,
center: new window.google.maps.LatLng(51.507937, -0.076188), // default to London
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
map.setOptions(myOptions);
directionsDisplay.setMap(map);
},
fitBounds: function (map) {
var bounds = new window.google.maps.LatLngBounds();
// extend bounds for each record
jQuery.each(stops, function (key, val) {
var myLatlng = new window.google.maps.LatLng(val.Geometry.Latitude, val.Geometry.Longitude);
bounds.extend(myLatlng);
});
map.fitBounds(bounds);
},
calcRoute: function (directionsService, directionsDisplay) {
var batches = [];
var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
var itemsCounter = 0;
var wayptsExist = stops.length > 0;
while (wayptsExist) {
var subBatch = [];
var subitemsCounter = 0;
for (var j = itemsCounter; j < stops.length; j++) {
subitemsCounter++;
subBatch.push({
location: new window.google.maps.LatLng(stops[j].Geometry.Latitude, stops[j].Geometry.Longitude),
stopover: true
});
if (subitemsCounter == itemsPerBatch)
break;
}
itemsCounter += subitemsCounter;
batches.push(subBatch);
wayptsExist = itemsCounter < stops.length;
// If it runs again there are still points. Minus 1 before continuing to
// start up with end of previous tour leg
itemsCounter--;
}
// now we should have a 2 dimensional array with a list of a list of waypoints
var combinedResults;
var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
var directionsResultsReturned = 0;
for (var k = 0; k < batches.length; k++) {
var lastIndex = batches[k].length - 1;
var start = batches[k][0].location;
var end = batches[k][lastIndex].location;
// trim first and last entry from array
var waypts = [];
waypts = batches[k];
waypts.splice(0, 1);
waypts.splice(waypts.length - 1, 1);
var request = {
origin: start,
destination: end,
waypoints: waypts,
travelMode: window.google.maps.TravelMode.WALKING
};
(function (kk) {
directionsService.route(request, function (result, status) {
if (status == window.google.maps.DirectionsStatus.OK) {
var unsortedResult = { order: kk, result: result };
unsortedResults.push(unsortedResult);
directionsResultsReturned++;
if (directionsResultsReturned == batches.length) // we've received all the results. put to map
{
// sort the returned values into their correct order
unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
var count = 0;
for (var key in unsortedResults) {
if (unsortedResults[key].result != null) {
if (unsortedResults.hasOwnProperty(key)) {
if (count == 0) // first results. new up the combinedResults object
combinedResults = unsortedResults[key].result;
else {
// only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
// directionResults object, but enough to draw a path on the map, which is all I need
combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
}
count++;
}
}
}
directionsDisplay.setDirections(combinedResults);
}
}
});
})(k);
}
}
};
}
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
It works like a charm but I have problem to setup an infowindow for each waypoint. I would like to leave markers names like A , B ,C or generate it in otherway but to keep A,B,C or 1,2,3 pattern and I want to add infowindow to each marker which contains title text and link.
I was trying to find any info or examples but nothing works. Maybe someone have and idea how to easily add infowindow to this code.
Here is an example that draws the directions from scratch with custom markers and infowindows:
Example
If you use the suppressInfoWindows option on the DirectionsRenderer, you can just use the part of it that creates the markers and their associated infowindows.
Working example based on your code
Code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Google Maps JavaScript API v3 Example: Directions Waypoints</title>
<style>
#map{
width: 100%;
height: 450px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script>
jQuery(function() {
var stops = [
{"Geometry":{"Latitude":52.1615470947258,"Longitude":20.80514430999756}},
{"Geometry":{"Latitude":52.15991486090931,"Longitude":20.804049968719482}},
{"Geometry":{"Latitude":52.15772967999426,"Longitude":20.805788040161133}},
{"Geometry":{"Latitude":52.15586034371232,"Longitude":20.80460786819458}},
{"Geometry":{"Latitude":52.15923693975469,"Longitude":20.80113172531128}},
{"Geometry":{"Latitude":52.159849043774074, "Longitude":20.791990756988525}},
{"Geometry":{"Latitude":52.15986220720892,"Longitude":20.790467262268066}},
{"Geometry":{"Latitude":52.16202095784738,"Longitude":20.7806396484375}},
{"Geometry":{"Latitude":52.16088894313116,"Longitude":20.77737808227539}},
{"Geometry":{"Latitude":52.15255590234335,"Longitude":20.784244537353516}},
{"Geometry":{"Latitude":52.14747369312591,"Longitude":20.791218280792236}},
{"Geometry":{"Latitude":52.14963304460396,"Longitude":20.79387903213501}}
] ;
var map = new window.google.maps.Map(document.getElementById("map"));
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer({suppressMarkers: true});
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
window.tour.fitBounds(map);
if (stops.length > 1)
window.tour.calcRoute(directionsService, directionsDisplay);
});
function Tour_startUp(stops) {
if (!window.tour) window.tour = {
updateStops: function (newStops) {
stops = newStops;
},
// map: google map object
// directionsDisplay: google directionsDisplay object (comes in empty)
loadMap: function (map, directionsDisplay) {
var myOptions = {
zoom: 13,
center: new window.google.maps.LatLng(51.507937, -0.076188), // default to London
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
map.setOptions(myOptions);
directionsDisplay.setMap(map);
},
fitBounds: function (map) {
var bounds = new window.google.maps.LatLngBounds();
// extend bounds for each record
jQuery.each(stops, function (key, val) {
var myLatlng = new window.google.maps.LatLng(val.Geometry.Latitude, val.Geometry.Longitude);
bounds.extend(myLatlng);
});
map.fitBounds(bounds);
},
calcRoute: function (directionsService, directionsDisplay) {
var batches = [];
var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
var itemsCounter = 0;
var wayptsExist = stops.length > 0;
while (wayptsExist) {
var subBatch = [];
var subitemsCounter = 0;
for (var j = itemsCounter; j < stops.length; j++) {
subitemsCounter++;
subBatch.push({
location: new window.google.maps.LatLng(stops[j].Geometry.Latitude, stops[j].Geometry.Longitude),
stopover: true
});
if (subitemsCounter == itemsPerBatch)
break;
}
itemsCounter += subitemsCounter;
batches.push(subBatch);
wayptsExist = itemsCounter < stops.length;
// If it runs again there are still points. Minus 1 before continuing to
// start up with end of previous tour leg
itemsCounter--;
}
// now we should have a 2 dimensional array with a list of a list of waypoints
var combinedResults;
var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
var directionsResultsReturned = 0;
for (var k = 0; k < batches.length; k++) {
var lastIndex = batches[k].length - 1;
var start = batches[k][0].location;
var end = batches[k][lastIndex].location;
// trim first and last entry from array
var waypts = [];
waypts = batches[k];
waypts.splice(0, 1);
waypts.splice(waypts.length - 1, 1);
var request = {
origin: start,
destination: end,
waypoints: waypts,
travelMode: window.google.maps.TravelMode.WALKING
};
(function (kk) {
directionsService.route(request, function (result, status) {
if (status == window.google.maps.DirectionsStatus.OK) {
var unsortedResult = { order: kk, result: result };
unsortedResults.push(unsortedResult);
directionsResultsReturned++;
if (directionsResultsReturned == batches.length) // we've received all the results. put to map
{
// sort the returned values into their correct order
unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
var count = 0;
for (var key in unsortedResults) {
if (unsortedResults[key].result != null) {
if (unsortedResults.hasOwnProperty(key)) {
if (count == 0) // first results. new up the combinedResults object
combinedResults = unsortedResults[key].result;
else {
// only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
// directionResults object, but enough to draw a path on the map, which is all I need
combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
}
count++;
}
}
}
directionsDisplay.setDirections(combinedResults);
var legs = combinedResults.routes[0].legs;
// alert(legs.length);
for (var i=0; i < legs.length;i++){
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
createMarker(directionsDisplay.getMap(),legs[i].start_location,"marker"+i,"some text for marker "+i+"<br>"+legs[i].start_address,markerletter);
}
var i=legs.length;
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
createMarker(directionsDisplay.getMap(),legs[legs.length-1].end_location,"marker"+i,"some text for the "+i+"marker<br>"+legs[legs.length-1].end_address,markerletter);
}
}
});
})(k);
}
}
};
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
function getMarkerImage(iconStr) {
if ((typeof(iconStr)=="undefined") || (iconStr==null)) {
iconStr = "red";
}
if (!icons[iconStr]) {
icons[iconStr] = new google.maps.MarkerImage("http://www.google.com/mapfiles/marker"+ iconStr +".png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 6,20.
new google.maps.Point(9, 34));
}
return icons[iconStr];
}
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
new google.maps.Size(37, 34),
new google.maps.Point(0,0),
new google.maps.Point(9, 34));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var iconShape = {
coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
type: 'poly'
};
function createMarker(map, latlng, label, html, color) {
// alert("createMarker("+latlng+","+label+","+html+","+color+")");
var contentString = '<b>'+label+'</b><br>'+html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
shadow: iconShadow,
icon: getMarkerImage(color),
shape: iconShape,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>