Sankar V
Sankar V

Reputation: 4128

Google Maps API v3 - Directions with draggable alternate routes

I've successfully implemented google map direction service api : https://developers.google.com/maps/documentation/javascript/directions with 'draggble' option enabled. Is it possible to show all routes together if multiple routes are available between 2 locations?

The current code is similar to: https://developers.google.com/maps/documentation/javascript/examples/directions-draggable and I do have alternative routes available in response code as I've enabled provideRouteAlternatives: true.

I tried the solution provided in : How to display alternative route using google map api. But when I used that code, I found it draws multiple routes with independent markers. That is, if 4 routes are available, there will be 4 'A' locations and 4 'B' locations and while dragging - only one of them get selected. Please find the below screenshots.

Initial View:

Initial View

After dragging initial locations (issue with duplicate locations)

After dragging initial locations

I need to drag in such a way that, when the location A or B is dragged, there should not be any duplicates and alternate routes should be automatically shown.

My current code is as follows (API key not added here):

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Draggable directions</title>
    <style>
      #right-panel {
        font-family: 'Roboto','sans-serif';
        line-height: 30px;
        padding-left: 10px;
      }

      #right-panel select, #right-panel input {
        font-size: 15px;
      }

      #right-panel select {
        width: 100%;
      }

      #right-panel i {
        font-size: 12px;
      }
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #map {
        height: 100%;
        float: left;
        width: 63%;
        height: 100%;
      }
      #right-panel {
        float: right;
        width: 34%;
        height: 100%;
      }
      .panel {
        height: 100%;
        overflow: auto;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <div id="right-panel">
      <p>Total Distance: <span id="total"></span></p>
    </div>
    <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          zoom: 4,
          center: {lat: -24.345, lng: 134.46}  // Australia.
        });

        var directionsService = new google.maps.DirectionsService;
        var directionsDisplay = new google.maps.DirectionsRenderer({
          draggable: true,
          map: map,
          panel: document.getElementById('right-panel')
        });

        directionsDisplay.addListener('directions_changed', function() {
          computeTotalDistance(directionsDisplay.getDirections());
        });

        displayRoute('Rosedale, MD, USA', 'Savage, MD, USA', directionsService,
            directionsDisplay);
      }

      function displayRoute(origin, destination, service, display) {
        service.route({
          origin: origin,
          destination: destination,
          travelMode: 'DRIVING',
          avoidTolls: true,
          provideRouteAlternatives: true,
        }, function(response, status) {
          if (status === 'OK') {
            for (var i = 0, len = response.routes.length; i < len; i++) {
                new google.maps.DirectionsRenderer({
                    map: map,
                    directions: response,
                    routeIndex: i,
                    draggable : true,
                });
            }
            display.setDirections(response);
          } else {
            alert('Could not display directions due to: ' + status);
          }
        });
      }

      function computeTotalDistance(result) {
        var total = 0;
        var myroute = result.routes[0];
        for (var i = 0; i < myroute.legs.length; i++) {
          total += myroute.legs[i].distance.value;
        }
        total = total / 1000;
        document.getElementById('total').innerHTML = total + ' km';
      }
    </script>
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?key=API-KEY&callback=initMap">
    </script>
  </body>
</html>

Please help me. Thanks in advance!

Upvotes: 0

Views: 5118

Answers (1)

MrUpsidown
MrUpsidown

Reputation: 22490

Each route you draw is editable and has a start and end marker which means that you will always be dragging one of the routes marker and not all at once. You could use the suppressMarkers option to remove markers from the alternate routes but that wouldn't change a lot to the behavior.

The problem is that as each route is separate, if you move the start or end location, you should redraw every route otherwise only one will update.

That said, if you edit a route (other than by changing its start or end location) you should not redraw your routes. If you update the start or end location you will of course then lose any route waypoint you added. Unless you do something about that... which sounds like a pain.

var directionsService = new google.maps.DirectionsService();
var map;

function initialize() {

  var center = new google.maps.LatLng(0, 0);
  var myOptions = {
    zoom: 7,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    center: center
  }

  map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);

  var start = "Sadulpur, India";
  var end = "New Delhi, India";

  plotDirections(start, end);
}

function plotDirections(start, end) {

  var method = 'DRIVING';

  var request = {
    origin: start,
    destination: end,
    travelMode: google.maps.DirectionsTravelMode[method],
    provideRouteAlternatives: true
  };

  directionsService.route(request, function(response, status) {

    if (status == google.maps.DirectionsStatus.OK) {

      var routes = response.routes;
      var colors = ['red', 'green', 'blue', 'orange', 'yellow', 'black'];
      var directionsDisplays = [];

      // Reset the start and end variables to the actual coordinates
      start = response.routes[0].legs[0].start_location;
      end = response.routes[0].legs[0].end_location;

      // Loop through each route
      for (var i = 0; i < routes.length; i++) {

        var directionsDisplay = new google.maps.DirectionsRenderer({
          map: map,
          directions: response,
          routeIndex: i,
          draggable: true,
          polylineOptions: {

            strokeColor: colors[i],
            strokeWeight: 4,
            strokeOpacity: .3
          }
        });

        // Push the current renderer to an array
        directionsDisplays.push(directionsDisplay);

        // Listen for the directions_changed event for each route
        google.maps.event.addListener(directionsDisplay, 'directions_changed', (function(directionsDisplay, i) {

          return function() {

            var directions = directionsDisplay.getDirections();
            var new_start = directions.routes[0].legs[0].start_location;
            var new_end = directions.routes[0].legs[0].end_location;

            if ((new_start.toString() !== start.toString()) || (new_end.toString() !== end.toString())) {

              // Remove every route from map
              for (var j = 0; j < directionsDisplays.length; j++) {

                directionsDisplays[j].setMap(null);
              }

              // Redraw routes with new start/end coordinates
              plotDirections(new_start, new_end);
            }
          }
        })(directionsDisplay, i)); // End listener
      } // End route loop
    }
  });
}

initialize();
#map-canvas {
  height: 180px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>

JSFiddle demo

Upvotes: 2

Related Questions