Reputation: 1297
I would like to output multiple Google Map routes on to a single Google Map. The data is taken from an XML file which feature multiple markers. Each marker has a start point and an end point (in the form of latitude and longitude values). These markers are then added to the map and a call to the Google Maps Directions Service is made to draw a route between the start and end points of each marker.
The issue I'm having is that only one route is drawn (if I refresh the page it seems to just pick one of the markers at random and draw the directions between those two markers). The other markers aren't displayed at all.
I've console.logged the for loop to check it is running for each marker in the XML (it is). I'm guessing it is something to do with these two lines here, but that is a guess...
directionsDisplay = new google.maps.DirectionsRenderer();
directionsService = new google.maps.DirectionsService();
I've read this question - Using Google Maps 3 API to get multiple routes on a Map, but don't really understand the answer/know how relevant it is to my situation. Thanks.
jQuery(document).ready(function($) {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 13,
mapTypeId: 'roadmap'
});
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(pos);
map.setZoom(13);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
directionsDisplay = new google.maps.DirectionsRenderer();
directionsService = new google.maps.DirectionsService();
// Change this depending on the name of your PHP file
downloadUrl("xml.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var title = markers[i].getAttribute("title");
mode = markers[i].getAttribute("mode");
startpoint = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("startlat")),
parseFloat(markers[i].getAttribute("startlng")));
endpoint = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("endlat")),
parseFloat(markers[i].getAttribute("endlng")));
calcRoute();
console.log('marker');
}
});
directionsDisplay.setMap(map);
});
function calcRoute() {
var request = {
origin: startpoint,
destination: endpoint,
//waypoints: waypts,
travelMode: google.maps.DirectionsTravelMode[mode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
Upvotes: 4
Views: 3920
Reputation: 28850
I think the key point in the answer you linked to is that each route needs its own DirectionsRenderer
object. And it doesn't mention it, but it seems likely that each route should also have its own DirectionsService
object. You're sharing a single one of each these objects among all your routes. I suspect that these shared objects are getting overwritten for each route.
Here's an update that should fix that by creating new objects for each route:
jQuery(document).ready(function($) {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 13,
mapTypeId: 'roadmap'
});
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(pos);
map.setZoom(13);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
// Change this depending on the name of your PHP file
$.get("xml.php", function( xml ) {
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
addMarkerPair( markers[i] );
}
}, 'xml' );
});
function addMarkerPair( pair ) {
function get( name ) {
return pair.getAttribute( name );
}
var title = get("title");
var mode = get("mode");
var startpoint = new google.maps.LatLng(
+get("startlat"),
+get("startlng")
);
var endpoint = new google.maps.LatLng(
+get("endlat"),
+get("endlng")
);
calcRoute( mode, startpoint, endpoint );
console.log('marker');
}
function calcRoute( mode, startpoint, endpoint ) {
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var request = {
origin: startpoint,
destination: endpoint,
//waypoints: waypts,
travelMode: google.maps.DirectionsTravelMode[mode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
I also took the liberty of fixing and simplifying a few things:
addMarkerPair
function for better readability.get
function inside addMarkerPair
as a shorthand for pair.getAttribute
.+
instead of parseInt
. Either one will do the same thing; I like +
for its brevity.var
declarations.calcRoute
as function parameters instead of global variables.$.get
instead of downloadUrl
. No need for your own function when jQuery has it already.Also, as another alternative to the XML parsing, you could use jQuery to access the XML elements. But I stuck with code closer to how you're already doing it.
Upvotes: 4