Fit Bounds in Google Map Render Directions
Asked Answered
P

2

5

I am trying to render directions for 48 waypoints, but google only allows 8 waypoints to be rendered per request. so I do multiple requests (in my case 6). However, the API somehow doed fitBounds() for the last request.

How can I show all the 48 waypoints in one map using fitBounds() and/or setZoom()

My code is as below: -

function DisplayDirection(directionList){

    var interval = 8; // upper bound for usage limits in google directions API is 8
    var startIndex =0;
    var maxmimumIndex = directionList.length-1; // Total number of waypoints in this route
    var partialEndIndex = interval-1; // end waypoint at start
    var iteration = 0; // loop controler
    directionsService = new google.maps.DirectionsService();
    var resultSet = new Array();
    var directionsDisplayList = new Array();
    var resultsCached = 0;
    var bounds = new google.maps.LatLngBounds();

    do { //do...while to iterate over multiple requests
        iteration++;
        if(iteration>1){
            startIndex = startIndex+interval;
            partialEndIndex = startIndex+interval;
        }

        var directionsDisplay = new google.maps.DirectionsRenderer({
                markerOptions: {
                    visible:false
                }      
            });
        directionsDisplayList.push(
            directionsDisplay
        ); 

        directionsDisplayList[iteration-1].setMap(map);

        var origin = directionList[startIndex];
        var destination = partialEndIndex < maxmimumIndex ? directionList[partialEndIndex]:directionList[maxmimumIndex];
        waypoints = new Array();

        for(var i=startIndex+1;i<partialEndIndex;i++){
            if(i>maxmimumIndex){                
                break;
            }       

            waypoints.push(
                {
                    location:directionList[i],
                    stopover:true
                }
            );
            latlong = directionList[i].split(","); //
            lat = latlong[0];  //
            lng = latlong[1]; //
            bounds.extend (new google.maps.LatLng(lat,lng)); //extend the bounds            
        }

        var request = {
            origin: origin,
            destination: destination,
            waypoints : waypoints,
            provideRouteAlternatives:false,
            travelMode: google.maps.TravelMode.WALKING,
            unitSystem: google.maps.UnitSystem.METRIC
        }

        directionsService.route(request, function(result, status) {
            if(status == google.maps.DirectionsStatus.OK) {
                //Cashe the results to render directions//
                resultSet.push(result);                             
                if(resultSet.length==iteration){
                    for(var i=0; i<iteration; i++){
                        directionsDisplayList[i].setDirections(resultSet[i]);                                                           
                    }
                    map.fitBounds(bounds);                  
                }                   
            }           
        });

    }while (partialEndIndex <= maxmimumIndex);      
}
Placet answered 24/1, 2013 at 1:5 Comment(2)
Consider showing only the relevant parts of the code to let others identify the problem better.Wisner
Sorry I just realised the whole code was pastedPlacet
W
-1

You cannot prevent from a fitBounds() to happen at the last request.

How about using the latlngs of origin and destination and do a fitBounds() manually in coding after the last request? I think that should do the work.

Wisner answered 24/1, 2013 at 5:45 Comment(2)
Is there a way to disable auto fitBounds and zoom?Placet
Not sure why you want to do that. Then you will need to manually scroll the map and zoom to required level. Not a good idea IMO.Wisner
D
9

Use the preserveViewport option of the DirectionsRenderer to prevent the automatic zoom to the route, then set the viewport you like.

{preserveViewport: true}

Then combine the bounds returned in each individual directions result with google.maps.LatLngBounds.union

function DisplayDirection(directionList) {
  var interval = 8; // upper bound for usage limits in google directions API is 8
  var startIndex = 0;
  var maxmimumIndex = directionList.length - 1; // Total number of waypoints in this route
  var partialEndIndex = interval - 1; // end waypoint at start
  var iteration = 0; // loop controler
  directionsService = new google.maps.DirectionsService();
  var resultSet = new Array();
  var directionsDisplayList = new Array();
  var resultsCached = 0;
  var bounds = new google.maps.LatLngBounds();

  do { //do...while to iterate over multiple requests
    iteration++;
    if (iteration > 1) {
      startIndex = startIndex + interval;
      partialEndIndex = startIndex + interval;
    }

    var directionsDisplay = new google.maps.DirectionsRenderer({
      preserveViewport: true, // prevent auto zoom to result
      markerOptions: {
        visible: false
      }
    });
    directionsDisplayList.push(
      directionsDisplay
    );

    directionsDisplayList[iteration - 1].setMap(map);

    var origin = directionList[startIndex];
    var destination = partialEndIndex < maxmimumIndex ? directionList[partialEndIndex] : directionList[maxmimumIndex];
    waypoints = new Array();

    for (var i = startIndex + 1; i < partialEndIndex; i++) {
      if (i > maxmimumIndex) {
        break;
      }

      waypoints.push({
        location: directionList[i],
        stopover: true
      });
      latlong = directionList[i].split(","); //
      lat = latlong[0]; //
      lng = latlong[1]; //
      bounds.extend(new google.maps.LatLng(lat, lng)); //extend the bounds            
    }

    var request = {
      origin: origin,
      destination: destination,
      waypoints: waypoints,
      provideRouteAlternatives: false,
      travelMode: google.maps.TravelMode.WALKING,
      unitSystem: google.maps.UnitSystem.METRIC
    }

    directionsService.route(request, function(result, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        //Cashe the results to render directions//
        resultSet.push(result);
        if (resultSet.length == iteration) {
          // empty bounds
          var bounds = new google.maps.LatLngBounds();
          for (var i = 0; i < iteration; i++) {
            directionsDisplayList[i].setDirections(resultSet[i]);
            // combine all the bounds of the results together with union
            if (i == 0) {
              bounds = resultSet[i].routes[0].bounds;
            } else {
              bounds.union(resultSet[i].routes[0].bounds);
            }
          }
          // fit the map to the resulting bounds
          map.fitBounds(bounds);
        }
      }
    });

  } while (partialEndIndex <= maxmimumIndex);
}

proof of concept fiddle (with 51 points)

code snippet:

var geocoder;
var map;

function initialize() {
  map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(37.4419, -122.1419),
      zoom: 3,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  document.getElementById('info').innerHTML = "entries:" + directionList.length;
  DisplayDirection(directionList);
}
google.maps.event.addDomListener(window, "load", initialize);

function DisplayDirection(directionList) {
  var interval = 8; // upper bound for usage limits in google directions API is 8
  var startIndex = 0;
  var maxmimumIndex = directionList.length - 1; // Total number of waypoints in this route
  var partialEndIndex = interval - 1; // end waypoint at start
  var iteration = 0; // loop controler
  directionsService = new google.maps.DirectionsService();
  var resultSet = new Array();
  var directionsDisplayList = new Array();
  var resultsCached = 0;
  var bounds = new google.maps.LatLngBounds();

  do { //do...while to iterate over multiple requests
    iteration++;
    if (iteration > 1) {
      startIndex = startIndex + interval;
      partialEndIndex = startIndex + interval;
    }

    var directionsDisplay = new google.maps.DirectionsRenderer({
      preserveViewport: true,
      markerOptions: {
        visible: false
      }
    });
    directionsDisplayList.push(
      directionsDisplay
    );

    directionsDisplayList[iteration - 1].setMap(map);

    var origin = directionList[startIndex];
    var destination = partialEndIndex < maxmimumIndex ? directionList[partialEndIndex] : directionList[maxmimumIndex];
    waypoints = new Array();

    for (var i = startIndex + 1; i < partialEndIndex; i++) {
      if (i > maxmimumIndex) {
        break;
      }

      waypoints.push({
        location: directionList[i],
        stopover: true
      });
      latlong = directionList[i].split(","); //
      lat = latlong[0]; //
      lng = latlong[1]; //
      bounds.extend(new google.maps.LatLng(lat, lng)); //extend the bounds            
    }

    var request = {
      origin: origin,
      destination: destination,
      waypoints: waypoints,
      provideRouteAlternatives: false,
      travelMode: google.maps.TravelMode.WALKING,
      unitSystem: google.maps.UnitSystem.METRIC
    }

    directionsService.route(request, function(result, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        //Cashe the results to render directions//
        resultSet.push(result);
        if (resultSet.length == iteration) {
          var bounds = new google.maps.LatLngBounds();
          for (var i = 0; i < iteration; i++) {
            directionsDisplayList[i].setDirections(resultSet[i]);
            if (i == 0) {
              bounds = resultSet[i].routes[0].bounds;
            } else {
              bounds.union(resultSet[i].routes[0].bounds);
            }
          }
          map.fitBounds(bounds);
        }
      }
    });

  } while (partialEndIndex <= maxmimumIndex);
}
var directionList = [
  "52.1615470947258,20.80514430999756",
  "52.15991486090931,20.804049968719482",
  "52.15772967999426,20.805788040161133",
  "52.15586034371232,20.80460786819458",
  "52.15923693975469,20.80113172531128",
  "52.159849043774074, 20.791990756988525",
  "52.15986220720892,20.790467262268066",
  "52.16202095784738,20.7806396484375",
  "52.16088894313116,20.77737808227539",
  "52.15255590234335,20.784244537353516",
  "52.14747369312591,20.791218280792236",
  "52.14963304460396,20.79387903213501",
  "52.1704725, 20.8118862",
  "52.1845184, 20.8400429",
  "52.200343, 20.8274304",
  "52.2015168, 20.799051599999984",
  "52.18724, 20.76437569999996",
  "52.18032700000001, 20.75405180000007",
  "52.1716078, 20.743079899999998",
  "49.9636566, 20.1216374",
  "51.8484715, 20.9852811",
  "51.40272359999999, 21.14713329999995",
  "51.2464536, 22.5684463",
  "51.1431232, 23.47119859999998",
  "50.7230879, 23.251968",
  "50.5826005, 22.053585999999996",
  "50.0411867, 21.999119599999972",
  "50.0121011, 20.9858407",
  "49.6174535, 20.7153326",
  "49.4215158, 20.959420799999975",
  "49.0018324, 21.23931189999996",
  "48.7163857, 21.2610746",
  "48.0963631, 20.762385999999992",
  "47.9025348, 20.3772284",
  "47.1621355, 20.1824712",
  "47.497912, 19.04023499999994",
  "48.3061414, 18.076375999999982",
  "48.1485965, 17.1077477",
  "48.2081743, 16.3738189",
  "48.30694, 14.28583",
  "48.16542, 14.03664",
  "48.05009, 14.41827",
  "47.80949, 13.055",
  "47.8571272, 12.1181047",
  "48.1351253, 11.58198",
  "52.52000659999999, 13.404953999999975",
  "53.5510846, 9.99368179999999",
  "50.1109221, 8.6821267",
  "52.3702157, 4.895167899999933",
  "50.8503396, 4.3517103",
  "48.856614, 2.3522219"
];
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="info"></div>
<div id="map_canvas"></div>
Degenerate answered 24/1, 2013 at 16:42 Comment(2)
This is definitely the best option. I have a case where I have to render multiple routes on the same map so without this option, there is no way of guaranteeing that you will see all routes in the same viewport.Whippletree
Thank You! I've lost 3 hours on this. Wish I could find your answer earlier.Handwoven
W
-1

You cannot prevent from a fitBounds() to happen at the last request.

How about using the latlngs of origin and destination and do a fitBounds() manually in coding after the last request? I think that should do the work.

Wisner answered 24/1, 2013 at 5:45 Comment(2)
Is there a way to disable auto fitBounds and zoom?Placet
Not sure why you want to do that. Then you will need to manually scroll the map and zoom to required level. Not a good idea IMO.Wisner

© 2022 - 2024 — McMap. All rights reserved.