Jochen Hebbrecht
Jochen Hebbrecht

Reputation: 743

Google Maps API v3 is not rerendering directions correctly

I created a small test project in here: http://jsfiddle.net/jochenhebbrecht/k3a3fvq0/3/

I clean routes using the following method:

// Clean previous routes
if (directionsDisplays.length > 0) {
    for(var i = 0; i < directionsDisplays.length; i++) {
        directionsDisplays[i].setMap(null);
    }
    directionsDisplays.length = 0;
}

I draw routes using the follow method:

// Draw all routes
if (routes.length > 0) {
    for (var i = 0; i < routes.length; i++) {
        (function(i){
            var route = routes[i];
            var request = {
                origin: route.origin,
                destination: route.destination,
                travelMode: google.maps.TravelMode.WALKING,
                waypoints: route.waypoints
            };

            var directionsDisplay = new google.maps.DirectionsRenderer({
                suppressMarkers: true,
                preserveViewport: true,
                polylineOptions: {
                    strokeColor: '#C6D300'
                }
            });
            directionsDisplay.setMap(map);
            directionsDisplays.push(directionsDisplay);

            directionsService.route(request, function (result, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    directionsDisplay.setDirections(result);
                }
            });
        })(i);
    }
}

I have a checkbox which show some routes on a map. If you check the box, routes are shown. If you uncheck the box, routes are removed.

However, if I check the box again (for a second time), not all routes are rendered correctly. You have to check/uncheck a couple of times to let it work ...

Any idea what I'm doing wrong?

Upvotes: 0

Views: 151

Answers (2)

geocodezip
geocodezip

Reputation: 161334

Check the status returned by your directions requests. If they fail due to OVER_QUERY_LIMIT, delay a short while and retry the failed requests. Also, don't request the routes every time they are displayed, if they are already available redisplay the route.

Note that the approach above will only work for the same order of magnitude of routes you currently have, if you have a lot more routes it will be prohibitively slow.

proof of concept fiddle

function highlightRoutes() {
  if (directionsDisplays.length > 0 && (directionsDisplays[0].getMap() == null)) {
    // redisplay the routes 
    for (var i = 0; i < directionsDisplays.length; i++) {
      directionsDisplays[i].setMap(map);
    }
  } else if (directionsDisplays.length > 0 && (directionsDisplays[0].getMap() != null)) {
    // hide the routes 
    for (var i = 0; i < directionsDisplays.length; i++) {
      directionsDisplays[i].setMap(null);
    }
  } else {
    var routes = new Array();

    if (jQuery('#chkBxBikeRoutes').attr('checked')) {
      routes.push.apply(routes, getBikeRoutes());
    }

    // Clean previous routes
    if (directionsDisplays.length > 0) {
      for (var i = 0; i < directionsDisplays.length; i++) {
        directionsDisplays[i].setMap(null);
      }
      directionsDisplays.length = 0;
    }

    // Draw all routes
    if (routes.length > 0) {
      for (var i = 0; i < routes.length; i++) {
        (function(i) {
          var route = routes[i];
          var request = {
            origin: route.origin,
            destination: route.destination,
            travelMode: google.maps.TravelMode.WALKING,
            waypoints: route.waypoints
          };

          var directionsDisplay = new google.maps.DirectionsRenderer({
            suppressMarkers: true,
            preserveViewport: true,
            polylineOptions: {
              strokeColor: '#C6D300'
            }
          });
          directionsDisplay.setMap(map);
          directionsDisplays.push(directionsDisplay);

          directionsService.route(request, function(result, status) {
            if (status == google.maps.DirectionsStatus.OK) {
              directionsDisplay.setDirections(result);
            } else if (status == google.maps.DirectionsStatus.OVER_QUERY_LIMIT) {
              //document.getElementById("status").innerHTML += request.origin+":"+request.destination+"status:"+status+"<br>";
              setTimeout(function() {
                directionsService.route(request, function(result, status) {
                  if (status == google.maps.DirectionsStatus.OK) {
                    directionsDisplay.setDirections(result);
                  } else {
                    document.getElementById("status").innerHTML += request.origin + ":" + request.destination + "status:" + status + "<br>";
                  }
                })
              }, 2000);
            } else {
              document.getElementById("status").innerHTML += request.origin + ":" + request.destination + "status:" + status + "<br>";
            }
          });
        })(i);
      }
    }
  }
}

Upvotes: 1

MrUpsidown
MrUpsidown

Reputation: 22490

Unfortunately you cannot do that.

Update your code as shown below and you will see what happens:

if (status == google.maps.DirectionsStatus.OK) {
    directionsDisplay.setDirections(result);
} else {
    alert(status);
}

You will get several OVER_QUERY_LIMIT status messages.

More information can be found here:

Upvotes: 0

Related Questions