Adding travel modes and waypoints to Google Maps directions

03 September 2012

In earlier tutorials we've learned how to add google maps with directions to your site and how to add a custom marker icon and in this tutorial we'll learn how to add buttons to switch between all available travel modes (driving, bicycling, public transportation and walking).
View demo

The google maps documentation on travel modes tells us we can add the option to the direction request, but not how to make this a dynamic option.



We need three parts in the HTML body. First we need a placeholder for the map:

<div id="map_canvas" style="width:100%; height:300px"></div>

Next part is the form for the directions options (all styling removed):

<form action="/routebeschrijving" onSubmit="calcRoute();return false;" id="routeForm">
    <label>
      From: <br />
      <input type="text" id="routeStart" value="amsteleindstraat, oss">
    </label>
    <label>
      Via: (optional)<br />
      <input type="text" id="routeVia" value="bessenlaan, oss">
    </label>
    <label>Travel mode:</label>
    <label><input type="radio" name="travelMode" value="DRIVING" checked /> Driving</label>
    <label><input type="radio" name="travelMode" value="BICYCLING" /> Bicylcing</label>
    <label><input type="radio" name="travelMode" value="TRANSIT" /> Public transport</label>
    <label><input type="radio" name="travelMode" value="WALKING" /> Walking</label>
    <input type="submit" value="Calculate route">
  </form>

And last, but not least, you'll need a placeholder to display the directions in:

<div id="directionsPanel">
    Enter a destination and click "Calculate route".
</div>

And then, back in the section of the page, add these two lines to include jQuery and the Google Maps API:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>

Then comes the most difficult part. It's not really different with the code from the previous directions tutorial. The site centers the map around the end-point of the route and adds a marker to that position. The default travel mode is "driving". You can change the default mode by moving the "checked" attribute to the radio formfield with the value you want to be the default option.

<script type="text/javascript">
  var directionDisplay;
var directionsService = new google.maps.DirectionsService();
function initialize() {
  var latlng = new google.maps.LatLng(51.764696,5.526042);
  // set direction render options
  var rendererOptions = { draggable: true };
  directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
  var myOptions = {
    zoom: 14,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    mapTypeControl: false
  };
  // add the map to the map placeholder
  var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
  directionsDisplay.setMap(map);
  directionsDisplay.setPanel(document.getElementById("directionsPanel"));
  // Add a marker to the map for the end-point of the directions.
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title:"Rodderhof, Oss"
  });
}
function calcRoute() {
  // get the travelmode, startpoint and via point from the form  
  var travelMode = $('input[name="travelMode"]:checked').val();
  var start = $("#routeStart").val();
  var via = $("#routeVia").val();
 
  if (travelMode == 'TRANSIT') {
    via = ''; // if the travel mode is transit, don't use the via waypoint because that will not work
  }
  var end = "51.764696,5.526042"; // endpoint is a geolocation
  var waypoints = []; // init an empty waypoints array
  if (via != '') {
    // if waypoints (via) are set, add them to the waypoints array
    waypoints.push({
      location: via,
      stopover: true
    });
  }
  var request = {
    origin: start,
    destination: end,
    waypoints: waypoints,
    unitSystem: google.maps.UnitSystem.IMPERIAL,
    travelMode: google.maps.DirectionsTravelMode[travelMode]
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      $('#directionsPanel').empty(); // clear the directions panel before adding new directions
      directionsDisplay.setDirections(response);
    } else {
      // alert an error message when the route could nog be calculated.
      if (status == 'ZERO_RESULTS') {
        alert('No route could be found between the origin and destination.');
      } else if (status == 'UNKNOWN_ERROR') {
        alert('A directions request could not be processed due to a server error. The request may succeed if you try again.');
      } else if (status == 'REQUEST_DENIED') {
        alert('This webpage is not allowed to use the directions service.');
      } else if (status == 'OVER_QUERY_LIMIT') {
        alert('The webpage has gone over the requests limit in too short a period of time.');
      } else if (status == 'NOT_FOUND') {
        alert('At least one of the origin, destination, or waypoints could not be geocoded.');
      } else if (status == 'INVALID_REQUEST') {
        alert('The DirectionsRequest provided was invalid.');        
      } else {
        alert("There was an unknown error in your request. Requeststatus: nn"+status);
      }
    }
  });
}
</script>

The comment lines in the code explain what line does what. Look at the demo, or copy/paste the complete page (below) to implement it on your own server or computer.

<!DOCTYPE html />
<html>
<head>
<title>Extensive Google Maps Directions demo</title>
<link href='http://fonts.googleapis.com/css?family=Terminal+Dosis:800,600' rel='stylesheet' type='text/css'>
  <style type="text/css">
  body {
    font-family: 'Terminal Dosis', sans-serif;
    font-size: 18px;
    color: #333;
    background: #CCC; /* background color */ 
    padding: 0 0 30px 0;
    margin: 10px 0px;
    overflow-y: scroll;
  }
  td {
    font-size: 18px; 
  }
  h1 {
    text-align: center;
    font-family: 'Terminal Dosis', sans-serif;
    font-size: 60px;
    color: #EEEEEE;
    text-shadow: 0px -1px 0px #AAA, 0px 1px 0px #EEEEEE;
    margin: 0px 0px 20px 0px;
  }
  input {
    font-family: 'Terminal Dosis', sans-serif;
    font-size: 22px;
    padding: 7px 8px;
    border: 0px;
    box-shadow: 0px 0px 6px #999;
    border-radius: 10px;
  }
  input[type="text"] {
    width: 300px;
  }
  input[type="submit"] {
    padding: 6px 20px; 
    margin: 20px 0 0 0;
  }
  #routeForm {
    width: 100%;
    text-align: center;
    margin-top: 20px;
  }
  #directionsPanel {
    background: #FFFFFF;
    width: 800px;
    padding: 20px;
    margin: 0 auto;
    box-shadow: 0px 0px 6px #999;
    border-radius: 10px;
    font-size: 20px;
  }
  .adp-directions {
    width: 100%; 
  }
  form label {
    display: block;
    padding: 4px 0px;
  }
  </style>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
function initialize() {
  var latlng = new google.maps.LatLng(51.764696,5.526042);
  // set direction render options
  var rendererOptions = { draggable: true };
  directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
  var myOptions = {
    zoom: 14,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    mapTypeControl: false
  };
  // add the map to the map placeholder
  var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
  directionsDisplay.setMap(map);
  directionsDisplay.setPanel(document.getElementById("directionsPanel"));
  // Add a marker to the map for the end-point of the directions.
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title:"Rodderhof, Oss"
  });
}
function calcRoute() {
  // get the travelmode, startpoint and via point from the form  
  var travelMode = $('input[name="travelMode"]:checked').val();
  var start = $("#routeStart").val();
  var via = $("#routeVia").val();
 
  if (travelMode == 'TRANSIT') {
    via = ''; // if the travel mode is transit, don't use the via waypoint because that will not work
  }
  var end = "51.764696,5.526042"; // endpoint is a geolocation
  var waypoints = []; // init an empty waypoints array
  if (via != '') {
    // if waypoints (via) are set, add them to the waypoints array
    waypoints.push({
      location: via,
      stopover: true
    });
  }
  var request = {
    origin: start,
    destination: end,
    waypoints: waypoints,
    unitSystem: google.maps.UnitSystem.IMPERIAL,
    travelMode: google.maps.DirectionsTravelMode[travelMode]
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      $('#directionsPanel').empty(); // clear the directions panel before adding new directions
      directionsDisplay.setDirections(response);
    } else {
      // alert an error message when the route could nog be calculated.
      if (status == 'ZERO_RESULTS') {
        alert('No route could be found between the origin and destination.');
      } else if (status == 'UNKNOWN_ERROR') {
        alert('A directions request could not be processed due to a server error. The request may succeed if you try again.');
      } else if (status == 'REQUEST_DENIED') {
        alert('This webpage is not allowed to use the directions service.');
      } else if (status == 'OVER_QUERY_LIMIT') {
        alert('The webpage has gone over the requests limit in too short a period of time.');
      } else if (status == 'NOT_FOUND') {
        alert('At least one of the origin, destination, or waypoints could not be geocoded.');
      } else if (status == 'INVALID_REQUEST') {
        alert('The DirectionsRequest provided was invalid.');        
      } else {
        alert("There was an unknown error in your request. Requeststatus: nn"+status);
      }
    }
  });
}
</script>
</head>
<body onLoad="initialize()">
  <h1>Extensive Google Maps Directions</h1>
  <div id="map_canvas" style="width:100%; height:300px"></div>   
  <form action="/routebeschrijving" onSubmit="calcRoute();return false;" id="routeForm">
    <div style="overflow: hidden; width: 500px; margin: 0 auto;">
      <div style="width: 350px; float: left; text-align: left;">
        <label>
          From: <br />
          <input type="text" id="routeStart" value="amsteleindstraat, oss">
        </label>
        <label>
          Via: (optional)<br />
          <input type="text" id="routeVia" value="bessenlaan, oss">
        </label>
      </div>
      <div style="width: 150px; float: left; text-align: left;">
        <label>Travel mode:</label>
        <label><input type="radio" name="travelMode" value="DRIVING" checked /> Driving</label>
        <label><input type="radio" name="travelMode" value="BICYCLING" /> Bicylcing</label>
        <label><input type="radio" name="travelMode" value="TRANSIT" /> Public transport</label>
        <label><input type="radio" name="travelMode" value="WALKING" /> Walking</label>
      </div>
    </div>
    <input type="submit" value="Calculate route">
  </form>
  <div id="directionsPanel">
    Enter a destination and click "Calculate route".
  </div>
</body>
</html>
You must have JavaScript enabled to use this form!

Leave a comment!

  1. Your mail is safe with me. It's only only used to display your Gravatar image!

39 comments

Previous Page 2 of 4 Next
  1. Gravatar

    Tom

    04 July 2015

    Nice post! Helped alot and working fine.

  2. Gravatar

    Jarek

    21 May 2015

    The example is not working!

  3. Gravatar

    Bahram

    28 January 2015

    Hi dear. Can I use this code on my weblog, please?
    Thanks

  4. Gravatar

    marakud

    30 November 2014

    Hi ! thx for this code.
    It's very helpfull !

    But i've got an issue with the code.
    When i try it, i've got no result , it try to reach /routebeschrijving?travelMode=DRIVING and don't find it.

    why ?

  5. Gravatar

    Stefan

    26 October 2014

    Thx for your nice work. If anyone is interested to fill into the "routeVia" input the current postal address of a user. I have a little snippet, sorry for my bad English ;-)

    The only problem i have is the TRANSIT option.

    var geocoder;
    geocoder = new google.maps.Geocoder();

    // Automatic geo localisation
    function codeLatLng() {
    if(navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
    var pos = new google.maps.LatLng(position.coords.latitude,
    position.coords.longitude);

    geocoder.geocode({'latLng': pos}, function(results, status) {

    if (status == google.maps.GeocoderStatus.OK) {
    if (results[1]) {
    document.getElementById("routeVia").value = results[0].formatted_address;
    } else {
    //alert("No results found");
    }
    } else {
    //alert("Geocoder failed due to: " + status);
    }
    });

    }, function() {
    //
    });
    }
    }


    Best wishes from Germany

  6. Gravatar

    Oscar J

    23 October 2014

    what a beautiful example!!! million thanks my friend!!!

  7. Gravatar

    Jean Pierre

    14 March 2014

    hi guys,
    I need a tutorial for this kind of application:
    - an app that gets my location and shows it with a marker on Google map.
    - this app should have a button and when I click on it:
    It select from my database nearest restaurants (within any range, maybe 1 miles) and show them with markers on the map.
    =>of course restaurants are stored in the database with their names and coordinates (latitude & longitude).

    If anyone ever seen any tutorial to do such an app, please tell me.
    Thx

  8. Gravatar

    Jean Pierre

    14 March 2014

    hi guys,
    I need this kind of application:
    - an app that gets my location and shows it with a marker on Google map.
    - this app should have a button and when I click on it:
    It select from my database nearest restaurants (within any range, maybe 1 miles) and show them with markers on the map.
    =>of course restaurants are stored in the database with their names and coordinates (latitude & longitude).

    If anyone ever seen any tutorial to do such an app, please tell me.
    Thx

  9. Gravatar

    Johan van Tongeren

    20 January 2014

    @kedar: yes this is possible. Google maps determines what to use depending on the language of the user. You can override this using the "unit" parameter, but I strongly suggest using the automatic function of the google maps API.

  10. Gravatar

    Kedar

    20 January 2014

    is there a way we get the Distance calculation in METERS instead of MILES?
    Great tutorial by the way ;)

Previous Page 2 of 4 Next