Displaying Multiple Routes using Google Maps API

Recently I have been playing around with the Google Maps JavaScript API and it is really intuitive to pick up. If you want to learn something different, grab an API key and start programming.

UPDATE: over time the code boxes on this page gained some additional HTML tags, and lost some formatting - I have now fixed this. I have also created a demo here

The Experiment

Using data that I have collected I decided to visualise my work days on a Google Map. I travel around locally and thought it was a good dataset to start tinkering upon.

This was easier than I thought.

You simply structure a request object and pass it into to a Direction Service Object and wait for Google's servers to respond via your callback function. After checking that the directions are "OK", you can iterate through the results object or pass it to a DirectionsRenderer Object provided by the Google API.

That's it you have requested and displayed a route.

What if you want another route?

Making a new request and displaying it using the same renderer object REPLACES your existing route. I wanted to display multiple routes on the same map. Not knowing where to begin and my mind drawing a blank I approached Google for inspiration. The only related suggestion was this from StackOverflow:

http://stackoverflow.com/questions/5451770/demo-for-displaying-multiple-google-directions-google-maps-api-v3.

Which in turn links to an example:

http://joshdcompton.com/google_maps/mult_directions/test.html.

Under the hood (a quick "View Source") provides a solution. Although provided in a bad design pattern it is functional and proves a point. You need a DirectionsRenderer for each route. Multiple DirectionsRenderer objects, sounds like they should be stacked in an Array. This works well:

// cur is used later to manage the location in the renderArray[]
    var cur = 0;
// requestArray - just going to be an array of DirectionRequest Objects, 
// you need to to populate this!
// renderArray - to be used to store multiple DirectionRenderers.
// map - the Google Map object.
    var requestArray = [], renderArray = [], map;
// Kickstart the process of requesting Directions
    submitRequests();
    function submitRequests(){
    requestLength = requestArray.length
        for (var i = 0;  i < requestLength; i++){
            console.log("Submitting request");
            directionsService.route(requestArray[i], directionResults);
          }
    }
/*
 * Callback function provided to the Maps API Direction Service. It creates
 * a new DirectionsRenderer to manage the new route without overriding the
 * old route
 *
 * @param result - the route information
 * @param status - Success or Fail
*/
    function directionResults(result, status) {
        console.log("Receiving request for route");
        if (status == google.maps.DirectionsStatus.OK) {
            renderArray[cur] = new google.maps.DirectionsRenderer();
            renderArray[cur].setMap(map);
            renderArray[cur].setDirections(result);
            cur++
        }
    }

The Directions service is Asynchronous, which means you have to wait for a response before displaying it, hence a callback method. This also means that the results may not come back in the same order. If you want to associate the route with the request you have to submit each request and then wait for the response. This would allow you to create a Legend, or retrieve information about the route that is appropriate for the request.

I settled for this, after changing the request array to hold a requestID as part of the object:

function processRequests(){
  console.log("Processing requests");
  //Counter to track request submission;
  var cur = 0;
  if(renderArray.length > 0){
    for(var r=0; r < renderArray.length; r++){
      console.log(r);
      renderArray[r].setMap(null);
    }
  }
  submitRequest();
  function nextRequest(){
    cur++;
    if(cur >= requestArray.length){
      console.log("Done");
      return;
    }
    submitRequest();
  }
  function submitRequest(){
    console.log("Submitting request for: ", requestArray[cur].requestID);
    directionsService.route(requestArray[cur].request, directionResults);
  }
  /*
  *  Callback function provided to the Maps API Direction Service. It creates
  *  a new DirectionsRenderer to manage the new route without overriding the
  *  old route
  *
  *  @param result - the route information
  *  @param status - Success or Fail
  */
  function directionResults(result, status) {
    console.log("Receiving request for route: ", cur);
    if (status == google.maps.DirectionsStatus.OK) {
      renderArray[cur] = new google.maps.DirectionsRenderer();
      renderArray[cur].setMap(map);
      renderArray[cur].setDirections(result);
    }
    nextRequest();
}

I hope this helps anyone displaying multiple routes, you could also spice it up with an array of colours on each directions renderer? Please note that although this code works, it may not be the 'best' solution. It also does not initialise or create the Google map, or provide you with any request data. It is only meant to highlight my solution to a problem.

I may put up a live example soon. Live example here

If you need more information, or if something isn't clear let me know, I'm just a Contact Page away!

comments powered by Disqus