Sunday, June 17, 2018

Drawing Multiple Routes In One Map with Google Map

Lots of examples in Google Map tutorials and examples are about drawing directions, markers, searches - and all of them typically involve only drawing one set of markers into a "route". An example of this will be going from Boston, MA to Seattle, WA via Cleveland, OH then Chicago, IL. But I need to be make Google Map to draw multiple routes in a single map.

The purpose of this task is to compare the routes. Assuming, like the example above, I am going from Boston to Seattle - which route will be better? Or maybe closer to passing Detroit?

Or another use case: if my friend and I are both traveling out of NYC on 2 separate cars, I am going to Columbus, OH and my friend is going to Detroit, MI - and another friend needs to be dropped off in State College, PA - so which car should this friend join - my car or the other car?

So here is how you do it.
FIRST - you will need to get Google Map Javascript API Key - you can get it here. Once you get it and enable the needed APIs, you will need to use it in your script reference below.

SECOND - in your HTML markup - add script reference Google Map and substituting the YOUR_API_KEY with your real API key from above.
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <style type="text/css">
  5. #map {
  6. margin-top: 10px;
  7. height: 750px;
  8. width: 100%;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <div id="map"></div>
  14. <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" type="text/javascript"></script>
  15. </body>
  16. </html>
THIRD - initialize several global variables and create a javascript method called "initMap" - this is to initialize your map once the script from Google is loaded.
  1. var routeMapArray = [];
  2. var map;
  3. var defaultZoom = 11;
  4. var directionsService;
  5. var directionDisplayRenderEngineArray = [];
  6. var iconColor = '';
  7.  
  8. function initMap() {
  9. routeMapArray = [];
  10. directionsService = new google.maps.DirectionsService();
  11.  
  12. // center initially on NYC
  13. loadMap(new google.maps.LatLng(40.7128, -74.0060));
  14. }
FOURTH - Create a method called "loadMap" that takes 1 parameter and create a json payload for your routes.
  1. var loadMap = function(center) {
  2. var mapOptions = {
  3. zoom: 11,
  4. mapTypeControl: false,
  5. streetViewControl: false,
  6. mapTypeId: google.maps.MapTypeId.ROADMAP
  7. };
  8.  
  9. if (center !== undefined && center !== null) {
  10. mapOptions.center = center;
  11. }
  12.  
  13. // Some basic map setup (from the API docs)
  14. map = new google.maps.Map(document.getElementById('map'), mapOptions);
  15.  
  16. // Start the request making
  17. var requestArray = [{
  18. "origin": "New York, NY",
  19. "destination": "Seattle, WA",
  20. "waypoints": [{
  21. "location": "Detroit, MI",
  22. "stopover": true
  23. },
  24. {
  25. "location": "Denver, CO",
  26. "stopover": true
  27. }
  28. ],
  29. "travelMode": "DRIVING"
  30. },
  31. {
  32. "origin": "Boston, MA",
  33. "destination": "San Diego, CA",
  34. "waypoints": [{
  35. "location": "Dayton, OH",
  36. "stopover": true
  37. },
  38. {
  39. "location": "Las Vegas, NV",
  40. "stopover": true
  41. }
  42. ],
  43. "travelMode": "DRIVING"
  44. }
  45. ];
  46. processRequests(requestArray);
  47. };
FIFTH - We need to process the requests in order, one by one - using different renderer each time on the same map (this is the key).
  1. var processRequests = function(requestArray) {
  2. var bounds = new google.maps.LatLngBounds();
  3. var infoWindow = new google.maps.InfoWindow();
  4.  
  5. // Counter to track request submission and process one at a time;
  6. var i = 0;
  7. var position = "";
  8.  
  9. // Used to submit the request 'i'
  10. var submitRequest = function() {
  11. if (requestArray.length === 0) return;
  12. directionsService.route(requestArray[i], processDirectionResults);
  13. };
  14.  
  15. // Used as callback for the above request for current 'i'
  16. function processDirectionResults(result, status) {
  17. if (status === google.maps.DirectionsStatus.OK) {
  18. // Create a unique DirectionsRenderer 'i'
  19. directionDisplayRenderEngineArray[i] = new google.maps.DirectionsRenderer();
  20. directionDisplayRenderEngineArray[i].setMap(map);
  21.  
  22. if (i == 0) {
  23. bounds = new google.maps.LatLngBounds();
  24. }
  25. iconColor = "#000000";
  26.  
  27. directionDisplayRenderEngineArray[i].setOptions({
  28. preserveViewport: true,
  29. polylineOptions: {
  30. strokeWeight: 5,
  31. strokeOpacity: 0.8,
  32. strokeColor: iconColor
  33. },
  34. markerOptions: {}
  35. });
  36.  
  37. // Use this new renderer with the result
  38. directionDisplayRenderEngineArray[i].setDirections(result);
  39.  
  40. // adjust zooming
  41. if (i === 0) {
  42. bounds = directionDisplayRenderEngineArray[i].getDirections().routes[0].bounds;
  43. } else {
  44. bounds.union(directionDisplayRenderEngineArray[i].getDirections().routes[0].bounds);
  45. }
  46.  
  47. map.fitBounds(bounds);
  48. if (map.zoom > defaultZoom) {
  49. map.setZoom(defaultZoom);
  50. }
  51.  
  52. // and start the next request
  53. setTimeout(function() {
  54. nextRequest();
  55. }, 500);
  56. }
  57. }
  58.  
  59. function nextRequest() {
  60. // increment counter
  61. i++;
  62.  
  63. // next request if any
  64. if (i >= requestArray.length) {
  65. // No more to do
  66. return;
  67. }
  68.  
  69. // submit next request
  70. submitRequest();
  71. }
  72.  
  73. // begin processing
  74. submitRequest();
  75. };
SIXTH - Done. Make. profit. Here is a working JSFiddle for it.

No comments: