0

I am working on google map directions I am following the google's navigation app.

I am able to get all the possible alternative routes by DirectionsService and can give the polylines different colors I want the user to be able to select his desired path just bu clicking on the poly lines some how have have not found any thing for this.

My code:

directionsService.route(request, function(response, status) {
  var points = [];
  if (status == google.maps.DirectionsStatus.OK) {
    try {
      var polycolour = "";
      var Opacity = 0;
      //var PolyLine = '';
      for (var i = 0, len = response.routes.length; i < len; i++) {
        if (i == 0) {
          polycolour = "Blue";
          Opacity = 5;
        }
        else {
          polycolour = "grey";
          Opacity = 2;
        }
        directionsDisplay = new google.maps.DirectionsRenderer({
          map: map,
          directions: response,
          routeIndex: i,
          draggable : true,
          polylineOptions: {
            strokeColor: polycolour,
            strokeWeight: Opacity
          }
        });

        var infowindow2 = new google.maps.InfoWindow();
        //var step = 10;
        //alert(angular.toJson(response.routes[0].legs[0].steps[i]));

        infowindow2.setContent(""+((response.routes[i].legs[0].distance.value)/1000)+" KM");
        infowindow2.setPosition(response.routes[i].legs[0].steps[8].end_location);
        infowindow2.open(map);

      }
      //directionsDisplay.setMap(map);
      google.maps.event.addListener(directionsDisplay, 'click', function(){
        alert("helo");
      });
      //for (var k = 0, len = response.routes.length; k < len; k++) {
        //var myRoute = response.routes[k].legs[0];
        //for (var i = 0; i < myRoute.steps.length; i++) {
          //for (var j = 0; j < myRoute.steps[i].lat_lngs.length; j++) {
            // points.push(myRoute.steps[i].lat_lngs[j]);
          //}
        //}

        //var routLine = new google.maps.Polyline(
        //{
          //path: points,
          //strokeColor: "Red",
          //strokeOpacity: 0.5,
          // strokeWeight: 10
        // }
        // );
      // }
      // routLine.setMap(map)

      // Add a listener for the rightclick event on the routLine
      //google.maps.event.addListener(routLine, 'click', function(e){
      //try {
        //alert(angular.toJson(e));
      //}
      //catch (err)
      //{
        //  alert(err);
      //}
   // });

   //alert(angular.toJson(response.routes[0].legs[0].steps));
   //google.maps.event.addListener(PolyLine, 'routeindex_changed', function() {
     //alert("Bingo");
     //computeTotalDistance(directionsDisplay.getRouteIndex());
   //});
   //alert(response.routes.length);
   //directionsDisplay.setDirections(response);
   }
   catch (err)
   {
     alert(err);
   }
 }
});
duncan
  • 31,401
  • 13
  • 78
  • 99
Ghani Rehman
  • 21
  • 1
  • 5
  • is it possible to create a JSFiddle? – Aneesh Sivaraman Sep 01 '16 at 08:06
  • i have never done that before :( if you have ionic installed in your phone i can give you the app id of working enviroment – Ghani Rehman Sep 01 '16 at 08:10
  • The [`DirectionsRenderer`](https://developers.google.com/maps/documentation/javascript/reference#DirectionsRenderer) doesn't support a 'click' event. You need to render the routes as `google.maps.Polyline` objects if you want them to be clickable. – geocodezip Sep 01 '16 at 10:31
  • possible duplicate of [Google Maps click event on route](http://stackoverflow.com/questions/17902574/google-maps-click-event-on-route) – geocodezip Sep 01 '16 at 10:32
  • i have tried that as well in google.maps.polyline click event it just returns the latlng of the place clicked on poly line how can we mark that polyline as chosen – Ghani Rehman Sep 01 '16 at 10:36

1 Answers1

5

First you need to tell the request that you want alternative routes, like this

// for example
var request = {
  origin: start,
  destination: end,
  provideRouteAlternatives: true,               
  travelMode: google.maps.TravelMode[DRIVING]
};

Then you have multiple response.routes objects (notice, sometimes you only get 1 route).

directionsService.route(request, function(response, status) {
  if (status == google.maps.DirectionsStatus.OK) {
    for(var i in  response.routes ) {
      // ...
    }
  }
}

Now you can use response.routes[i] as the source for direction render.
Or you make your own polyline. Use response.routes[i].overview_path as the path

var line = new google.maps.Polyline({
  path: response.routes[i].overview_path,
  strokeColor: "#ff0000",  // you might want different colors per suggestion
  strokeOpacity: 0.7,
  strokeWeight: 3
});
line.setMap(map);

Here is an functioning example. Just change your API key.

As you asked for, clicking on a route highlights it

UPDATE: I like it this way.

Both grey lines and colored lines are generated. But highlighting only shows 1 of the suggestions on the map.

The big, grey line is nice to click on. So it gets the click event instead of the colored line.

This is also the easiest way to avoid the Z-index problem.

And I store data (duration, distance), that I show on an infoWindow

<!DOCTYPE html>
<html>
<head>
    <title>Google Map Direction Render Alternate Route How To Select Desired Path</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #map {
            height: 90%;
        }
    </style>
</head>
<body>
    <form id="form">
        <input id="from" placeholder="From" value="Brussel" />
        <input id="to" placeholder="To" value="Antwerpen" />
        <input type="submit" value="GO"  />
    </form>

    <div id="map"></div>
    <div id="info">
        <a href="http://stackoverflow.com/questions/39264760/google-map-direction-render-alternate-route-how-to-select-desired-path/39268344#39268344">Stackoverflow</a>
    </div>
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry"></script>
    <script>
        var map;
        var directionsService;
        var polylines = [];
        var shadows = [];
        var data = [];
        var infowindow;
        function initMap() {
            map = new google.maps.Map(document.getElementById('map'), {
                center: {lat: 50.84659376378408, lng: 4.3531406857355215},
                zoom: 12,
                mapTypeId: 'terrain'
            });
            google.maps.event.addDomListener(document.getElementById('form'), 'submit', function(e) {
                calcRoute(
                    document.getElementById('from').value,
                    document.getElementById('to').value
                );
                // prevent the form from really submitting
                e.preventDefault();
                return false;
            });
            directionsService = new google.maps.DirectionsService();
            // get the bounds of the polyline
            // http://stackoverflow.com/questions/3284808/getting-the-bounds-of-a-polyine-in-google-maps-api-v3
            google.maps.Polyline.prototype.getBounds = function(startBounds) {
                if(startBounds) {
                    var bounds = startBounds;
                }
                else {
                    var bounds = new google.maps.LatLngBounds();
                }
                this.getPath().forEach(function(item, index) {
                    bounds.extend(new google.maps.LatLng(item.lat(), item.lng()));
                });
                return bounds;
            };
        }
        // this function calculates multiple suggested routes.
        // We will draw 3 (broad stroke) suggested routs in grey.  These are broad to click on them easier.
        // We duplicate these routes with a thin, colored line; only route 0 is shown.
        function calcRoute(start, end) {
            var request = {
                origin: start,
                destination: end,
                provideRouteAlternatives: true,
                unitSystem: google.maps.UnitSystem.METRIC,
                travelMode: google.maps.TravelMode['DRIVING']
            };
            directionsService.route(request, function(response, status) {
                // clear former polylines
                for(var j in  polylines ) {
                    polylines[j].setMap(null);
                    shadows[j].setMap(null);
                }
                polylines = [];
                shadows = [];
                data = [];
                if (status == google.maps.DirectionsStatus.OK) {
                    var bounds = new google.maps.LatLngBounds();
                    for(var i in response.routes) {
                        // let's make the first suggestion highlighted;
                        var hide = (i==0 ? false : true);
                        var shadow = drawPolylineShadow(response.routes[i].overview_path, '#666666');
                        var line = drawPolyline(response.routes[i].overview_path, '#0000ff', hide);
                        polylines.push(line);
                        shadows.push(shadow);
                        // let's add some data for the infoWindow
                        data.push({
                            distance: response.routes[i].legs[0].distance,
                            duration: response.routes[i].legs[0].duration,
                            end_address: response.routes[i].legs[0].end_address,
                            start_address: response.routes[i].legs[0].start_address,
                            end_location: response.routes[i].legs[0].end_location,
                            start_location: response.routes[i].legs[0].start_location
                        });
                        bounds = line.getBounds(bounds);
                        google.maps.event.addListener(shadow, 'click', function(e) {
                            // detect which route was clicked on
                            var index = shadows.indexOf(this);
                            highlightRoute(index, e);
                        });

                    }
                    map.fitBounds(bounds);
                }
            });
        }
        // this makes one of the colored routes visible.
        function highlightRoute(index, e) {
            for(var j in  polylines ) {
                if(j==index) {
                    //var color = '#0000ff';
                    polylines[j].setMap(map);
                    // feel free to customise this string
                    var contentString =
                        '<span>'+ data[j].distance.text +'</span><br/>'+
                        '<span>'+ data[j].duration.text +'</span><br/>'+
                        '<span>route: '+ j +'</span><br/>'+
                        //'From: <span>'+ data[j].start_address +'</span><br/>'+
                        //'To: <span>'+ data[j].end_address +'</span><br/>'+
                        '';
                    if(e) {
                       var position = new google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
                        // it may be needed to close the previous infoWindow
                        if(infowindow) {
                            infowindow.close();
                            infowindow = null;
                        }
                        infowindow = new google.maps.InfoWindow({
                            content: contentString,
                            position: position,
                            map: map
                        });
                        //infowindow.open(map, polylines[j]);
                    }
                }
                else {
                    polylines[j].setMap(null);
                }
            }
        }
        // returns a polyline.
        // if hide is set to true, the line is not put on the map
        function drawPolyline(path, color, hide) {
            var line = new google.maps.Polyline({
                path: path,
                strokeColor: color,
                strokeOpacity: 0.9,
                strokeWeight: 3
            });
            if(! hide) {
                line.setMap(map);
            }
            return line;
        }
        function drawPolylineShadow(path, color, hide) {
            var line = new google.maps.Polyline({
                path: path,
                strokeColor: color,
                strokeOpacity: 0.4,
                strokeWeight: 7
            });
            if(! hide) {
                line.setMap(map);
            }
            return line;
        }
        google.maps.event.addDomListener(window, 'load', initMap);
    </script>
</body>
</html> 

earlier code. this changes the color of the polyLine

<!DOCTYPE html>
<html>
<head>
    <title>Suggested routes</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #map {
            height: 90%;
        }
    </style>
</head>
<body>
    <form id="form">
        <input id="from" placeholder="From" value="Brussel" />
        <input id="to" placeholder="To" value="Antwerpen" />
        <input type="submit" value="GO"  />
    </form>
    <div id="map"></div>
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry"></script>
    <script>
        var map;
        var directionsService;
        var polylines = [];

        function initMap() {
            map = new google.maps.Map(document.getElementById('map'), {
                center: {lat: 50.84659376378408, lng: 4.3531406857355215},
                zoom: 12,
                mapTypeId: 'terrain'
            });
            google.maps.event.addDomListener(document.getElementById('form'), 'submit', function(e) {
                calcRoute(
                    document.getElementById('from').value,
                    document.getElementById('to').value
                );
                // prevent the form from really submitting
                e.preventDefault();
                return false;
            });
            directionsService = new google.maps.DirectionsService();
            // get the bounds of the polyline
            // http://stackoverflow.com/questions/3284808/getting-the-bounds-of-a-polyine-in-google-maps-api-v3
            google.maps.Polyline.prototype.getBounds = function(startBounds) {
                if(startBounds) {
                    var bounds = startBounds;
                }
                else {
                    var bounds = new google.maps.LatLngBounds();
                }

                this.getPath().forEach(function(item, index) {
                    bounds.extend(new google.maps.LatLng(item.lat(), item.lng()));
                });
                return bounds;
            };
        }

        function calcRoute(start, end) {
            var request = {
                origin: start,
                destination: end,
                provideRouteAlternatives: true,
                unitSystem: google.maps.UnitSystem.METRIC,
                travelMode: google.maps.TravelMode['DRIVING']
            };
            directionsService.route(request, function(response, status) {
                // clear former polylines
                for(var j in  polylines ) {
                    polylines[j].setMap(null);
                }
                polylines = [];
                if (status == google.maps.DirectionsStatus.OK) {
                    var bounds = new google.maps.LatLngBounds();
                    // draw the lines in reverse orde, so the first one is on top (z-index)
                    for(var i=response.routes.length - 1; i>=0; i-- ) {
                        // let's make the first suggestion highlighted;
                        if(i==0) {
                            var color = '#0000ff';

                        }
                        else {
                            var color = '#999999';
                        }
                        var line = drawPolyline(response.routes[i].overview_path, color);
                        polylines.push(line);
                        bounds = line.getBounds(bounds);
                        google.maps.event.addListener(line, 'click', function() {
                            // detect which route was clicked on
                            var index = polylines.indexOf(this);
                            highlightRoute(index);
                        });
                    }
                    map.fitBounds(bounds);
                }
            });
        }

        function highlightRoute(index) {
            for(var j in  polylines ) {
                if(j==index) {
                    var color = '#0000ff';
                }
                else {
                    var color = '#999999';
                }
                polylines[j].setOptions({strokeColor: color});
            }
        }

        function drawPolyline(path, color) {
            var line = new google.maps.Polyline({
                path: path,
                strokeColor: color,
                strokeOpacity: 0.7,
                strokeWeight: 3
            });
            line.setMap(map);
            return line;
        }
        google.maps.event.addDomListener(window, 'load', initMap);
    </script>
</body>
</html>
Emmanuel Delay
  • 3,619
  • 1
  • 11
  • 17