It's the 15th anniversary of Google Maps Platform - Check out the latest news and announcements

Directions Service (Complex)

This example demonstrates the use of the DirectionsService object to fetch directions between landmarks in New York City. Markers are placed at each waypoint along the route. Click on a marker to display the directions associated with that waypoint.

Read the documentation.

TypeScript

function initMap(): void {
  const markerArray: google.maps.Marker[] = [];

  // Instantiate a directions service.
  const directionsService = new google.maps.DirectionsService();

  // Create a map and center it on Manhattan.
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 13,
      center: { lat: 40.771, lng: -73.974 },
    }
  );

  // Create a renderer for directions and bind it to the map.
  const directionsRenderer = new google.maps.DirectionsRenderer({ map: map });

  // Instantiate an info window to hold step text.
  const stepDisplay = new google.maps.InfoWindow();

  // Display the route between the initial start and end selections.
  calculateAndDisplayRoute(
    directionsRenderer,
    directionsService,
    markerArray,
    stepDisplay,
    map
  );

  // Listen to change events from the start and end lists.
  const onChangeHandler = function () {
    calculateAndDisplayRoute(
      directionsRenderer,
      directionsService,
      markerArray,
      stepDisplay,
      map
    );
  };
  (document.getElementById("start") as HTMLElement).addEventListener(
    "change",
    onChangeHandler
  );
  (document.getElementById("end") as HTMLElement).addEventListener(
    "change",
    onChangeHandler
  );
}

function calculateAndDisplayRoute(
  directionsRenderer: google.maps.DirectionsRenderer,
  directionsService: google.maps.DirectionsService,
  markerArray: google.maps.Marker[],
  stepDisplay: google.maps.InfoWindow,
  map: google.maps.Map
) {
  // First, remove any existing markers from the map.
  for (let i = 0; i < markerArray.length; i++) {
    markerArray[i].setMap(null);
  }

  // Retrieve the start and end locations and create a DirectionsRequest using
  // WALKING directions.
  directionsService.route(
    {
      origin: (document.getElementById("start") as HTMLInputElement).value,
      destination: (document.getElementById("end") as HTMLInputElement).value,
      travelMode: google.maps.TravelMode.WALKING,
    },
    (
      result: google.maps.DirectionsResult,
      status: google.maps.DirectionsStatus
    ) => {
      // Route the directions and pass the response to a function to create
      // markers for each step.
      if (status === "OK") {
        (document.getElementById("warnings-panel") as HTMLElement).innerHTML =
          "<b>" + result.routes[0].warnings + "</b>";
        directionsRenderer.setDirections(result);
        showSteps(result, markerArray, stepDisplay, map);
      } else {
        window.alert("Directions request failed due to " + status);
      }
    }
  );
}

function showSteps(
  directionResult: google.maps.DirectionsResult,
  markerArray: google.maps.Marker[],
  stepDisplay: google.maps.InfoWindow,
  map: google.maps.Map
) {
  // For each step, place a marker, and add the text to the marker's infowindow.
  // Also attach the marker to an array so we can keep track of it and remove it
  // when calculating new routes.
  const myRoute = directionResult.routes[0].legs[0];

  for (let i = 0; i < myRoute.steps.length; i++) {
    const marker = (markerArray[i] =
      markerArray[i] || new google.maps.Marker());
    marker.setMap(map);
    marker.setPosition(myRoute.steps[i].start_location);
    attachInstructionText(
      stepDisplay,
      marker,
      myRoute.steps[i].instructions,
      map
    );
  }
}

function attachInstructionText(
  stepDisplay: google.maps.InfoWindow,
  marker: google.maps.Marker,
  text: string,
  map: google.maps.Map
) {
  google.maps.event.addListener(marker, "click", () => {
    // Open an info window when the marker is clicked on, containing the text
    // of the step.
    stepDisplay.setContent(text);
    stepDisplay.open(map, marker);
  });
}

JavaScript

function initMap() {
  const markerArray = [];
  // Instantiate a directions service.
  const directionsService = new google.maps.DirectionsService();
  // Create a map and center it on Manhattan.
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 13,
    center: { lat: 40.771, lng: -73.974 },
  });
  // Create a renderer for directions and bind it to the map.
  const directionsRenderer = new google.maps.DirectionsRenderer({ map: map });
  // Instantiate an info window to hold step text.
  const stepDisplay = new google.maps.InfoWindow();
  // Display the route between the initial start and end selections.
  calculateAndDisplayRoute(
    directionsRenderer,
    directionsService,
    markerArray,
    stepDisplay,
    map
  );

  // Listen to change events from the start and end lists.
  const onChangeHandler = function () {
    calculateAndDisplayRoute(
      directionsRenderer,
      directionsService,
      markerArray,
      stepDisplay,
      map
    );
  };
  document.getElementById("start").addEventListener("change", onChangeHandler);
  document.getElementById("end").addEventListener("change", onChangeHandler);
}

function calculateAndDisplayRoute(
  directionsRenderer,
  directionsService,
  markerArray,
  stepDisplay,
  map
) {
  // First, remove any existing markers from the map.
  for (let i = 0; i < markerArray.length; i++) {
    markerArray[i].setMap(null);
  }
  // Retrieve the start and end locations and create a DirectionsRequest using
  // WALKING directions.
  directionsService.route(
    {
      origin: document.getElementById("start").value,
      destination: document.getElementById("end").value,
      travelMode: google.maps.TravelMode.WALKING,
    },
    (result, status) => {
      // Route the directions and pass the response to a function to create
      // markers for each step.
      if (status === "OK") {
        document.getElementById("warnings-panel").innerHTML =
          "<b>" + result.routes[0].warnings + "</b>";
        directionsRenderer.setDirections(result);
        showSteps(result, markerArray, stepDisplay, map);
      } else {
        window.alert("Directions request failed due to " + status);
      }
    }
  );
}

function showSteps(directionResult, markerArray, stepDisplay, map) {
  // For each step, place a marker, and add the text to the marker's infowindow.
  // Also attach the marker to an array so we can keep track of it and remove it
  // when calculating new routes.
  const myRoute = directionResult.routes[0].legs[0];

  for (let i = 0; i < myRoute.steps.length; i++) {
    const marker = (markerArray[i] =
      markerArray[i] || new google.maps.Marker());
    marker.setMap(map);
    marker.setPosition(myRoute.steps[i].start_location);
    attachInstructionText(
      stepDisplay,
      marker,
      myRoute.steps[i].instructions,
      map
    );
  }
}

function attachInstructionText(stepDisplay, marker, text, map) {
  google.maps.event.addListener(marker, "click", () => {
    // Open an info window when the marker is clicked on, containing the text
    // of the step.
    stepDisplay.setContent(text);
    stepDisplay.open(map, marker);
  });
}

CSS

/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
#map {
  height: 100%;
}

/* Optional: Makes the sample page fill the window. */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#floating-panel {
  position: absolute;
  top: 10px;
  left: 25%;
  z-index: 5;
  background-color: #fff;
  padding: 5px;
  border: 1px solid #999;
  text-align: center;
  font-family: "Roboto", "sans-serif";
  line-height: 30px;
  padding-left: 10px;
}

#warnings-panel {
  width: 100%;
  height: 10%;
  text-align: center;
}

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Directions Service (Complex)</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=&v=weekly"
      defer
    ></script>
    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script src="./app.js"></script>
  </head>
  <body>
    <div id="floating-panel">
      <b>Start: </b>
      <select id="start">
        <option value="penn station, new york, ny">Penn Station</option>
        <option value="grand central station, new york, ny">
          Grand Central Station
        </option>
        <option value="625 8th Avenue, New York, NY, 10018">
          Port Authority Bus Terminal
        </option>
        <option value="staten island ferry terminal, new york, ny">
          Staten Island Ferry Terminal
        </option>
        <option value="101 E 125th Street, New York, NY">
          Harlem - 125th St Station
        </option>
      </select>
      <b>End: </b>
      <select id="end">
        <option value="260 Broadway New York NY 10007">City Hall</option>
        <option value="W 49th St & 5th Ave, New York, NY 10020">
          Rockefeller Center
        </option>
        <option value="moma, New York, NY">MOMA</option>
        <option value="350 5th Ave, New York, NY, 10118">
          Empire State Building
        </option>
        <option value="253 West 125th Street, New York, NY">
          Apollo Theater
        </option>
        <option value="1 Wall St, New York, NY">Wall St</option>
      </select>
    </div>
    <div id="map"></div>
    &nbsp;
    <div id="warnings-panel"></div>
  </body>
</html>

All

<!DOCTYPE html>
<html>
  <head>
    <title>Directions Service (Complex)</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=&v=weekly"
      defer
    ></script>
    <style type="text/css">
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }

      /* Optional: Makes the sample page fill the window. */
      html,
      body {
        height: 100%;
        margin: 0;
        padding: 0;
      }

      #floating-panel {
        position: absolute;
        top: 10px;
        left: 25%;
        z-index: 5;
        background-color: #fff;
        padding: 5px;
        border: 1px solid #999;
        text-align: center;
        font-family: "Roboto", "sans-serif";
        line-height: 30px;
        padding-left: 10px;
      }

      #warnings-panel {
        width: 100%;
        height: 10%;
        text-align: center;
      }
    </style>
    <script>
      "use strict";

      function initMap() {
        const markerArray = []; // Instantiate a directions service.

        const directionsService = new google.maps.DirectionsService(); // Create a map and center it on Manhattan.

        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 13,
          center: {
            lat: 40.771,
            lng: -73.974,
          },
        }); // Create a renderer for directions and bind it to the map.

        const directionsRenderer = new google.maps.DirectionsRenderer({
          map: map,
        }); // Instantiate an info window to hold step text.

        const stepDisplay = new google.maps.InfoWindow(); // Display the route between the initial start and end selections.

        calculateAndDisplayRoute(
          directionsRenderer,
          directionsService,
          markerArray,
          stepDisplay,
          map
        ); // Listen to change events from the start and end lists.

        const onChangeHandler = function () {
          calculateAndDisplayRoute(
            directionsRenderer,
            directionsService,
            markerArray,
            stepDisplay,
            map
          );
        };

        document
          .getElementById("start")
          .addEventListener("change", onChangeHandler);
        document
          .getElementById("end")
          .addEventListener("change", onChangeHandler);
      }

      function calculateAndDisplayRoute(
        directionsRenderer,
        directionsService,
        markerArray,
        stepDisplay,
        map
      ) {
        // First, remove any existing markers from the map.
        for (let i = 0; i < markerArray.length; i++) {
          markerArray[i].setMap(null);
        } // Retrieve the start and end locations and create a DirectionsRequest using
        // WALKING directions.

        directionsService.route(
          {
            origin: document.getElementById("start").value,
            destination: document.getElementById("end").value,
            travelMode: google.maps.TravelMode.WALKING,
          },
          (result, status) => {
            // Route the directions and pass the response to a function to create
            // markers for each step.
            if (status === "OK") {
              document.getElementById("warnings-panel").innerHTML =
                "<b>" + result.routes[0].warnings + "</b>";
              directionsRenderer.setDirections(result);
              showSteps(result, markerArray, stepDisplay, map);
            } else {
              window.alert("Directions request failed due to " + status);
            }
          }
        );
      }

      function showSteps(directionResult, markerArray, stepDisplay, map) {
        // For each step, place a marker, and add the text to the marker's infowindow.
        // Also attach the marker to an array so we can keep track of it and remove it
        // when calculating new routes.
        const myRoute = directionResult.routes[0].legs[0];

        for (let i = 0; i < myRoute.steps.length; i++) {
          const marker = (markerArray[i] =
            markerArray[i] || new google.maps.Marker());
          marker.setMap(map);
          marker.setPosition(myRoute.steps[i].start_location);
          attachInstructionText(
            stepDisplay,
            marker,
            myRoute.steps[i].instructions,
            map
          );
        }
      }

      function attachInstructionText(stepDisplay, marker, text, map) {
        google.maps.event.addListener(marker, "click", () => {
          // Open an info window when the marker is clicked on, containing the text
          // of the step.
          stepDisplay.setContent(text);
          stepDisplay.open(map, marker);
        });
      }
    </script>
  </head>
  <body>
    <div id="floating-panel">
      <b>Start: </b>
      <select id="start">
        <option value="penn station, new york, ny">Penn Station</option>
        <option value="grand central station, new york, ny">
          Grand Central Station
        </option>
        <option value="625 8th Avenue, New York, NY, 10018">
          Port Authority Bus Terminal
        </option>
        <option value="staten island ferry terminal, new york, ny">
          Staten Island Ferry Terminal
        </option>
        <option value="101 E 125th Street, New York, NY">
          Harlem - 125th St Station
        </option>
      </select>
      <b>End: </b>
      <select id="end">
        <option value="260 Broadway New York NY 10007">City Hall</option>
        <option value="W 49th St & 5th Ave, New York, NY 10020">
          Rockefeller Center
        </option>
        <option value="moma, New York, NY">MOMA</option>
        <option value="350 5th Ave, New York, NY, 10118">
          Empire State Building
        </option>
        <option value="253 West 125th Street, New York, NY">
          Apollo Theater
        </option>
        <option value="1 Wall St, New York, NY">Wall St</option>
      </select>
    </div>
    <div id="map"></div>
    &nbsp;
    <div id="warnings-panel"></div>
  </body>
</html>
"use strict"; function initMap() { const markerArray = []; // Instantiate a directions service. const directionsService = new google.maps.DirectionsService(); // Create a map and center it on Manhattan. const map = new google.maps.Map(document.getElementById("map"), { zoom: 13, center: { lat: 40.771, lng: -73.974, }, }); // Create a renderer for directions and bind it to the map. const directionsRenderer = new google.maps.DirectionsRenderer({ map: map, }); // Instantiate an info window to hold step text. const stepDisplay = new google.maps.InfoWindow(); // Display the route between the initial start and end selections. calculateAndDisplayRoute( directionsRenderer, directionsService, markerArray, stepDisplay, map ); // Listen to change events from the start and end lists. const onChangeHandler = function () { calculateAndDisplayRoute( directionsRenderer, directionsService, markerArray, stepDisplay, map ); }; document.getElementById("start").addEventListener("change", onChangeHandler); document.getElementById("end").addEventListener("change", onChangeHandler); } function calculateAndDisplayRoute( directionsRenderer, directionsService, markerArray, stepDisplay, map ) { // First, remove any existing markers from the map. for (let i = 0; i < markerArray.length; i++) { markerArray[i].setMap(null); } // Retrieve the start and end locations and create a DirectionsRequest using // WALKING directions. directionsService.route( { origin: document.getElementById("start").value, destination: document.getElementById("end").value, travelMode: google.maps.TravelMode.WALKING, }, (result, status) => { // Route the directions and pass the response to a function to create // markers for each step. if (status === "OK") { document.getElementById("warnings-panel").innerHTML = "<b>" + result.routes[0].warnings + "</b>"; directionsRenderer.setDirections(result); showSteps(result, markerArray, stepDisplay, map); } else { window.alert("Directions request failed due to " + status); } } ); } function showSteps(directionResult, markerArray, stepDisplay, map) { // For each step, place a marker, and add the text to the marker's infowindow. // Also attach the marker to an array so we can keep track of it and remove it // when calculating new routes. const myRoute = directionResult.routes[0].legs[0]; for (let i = 0; i < myRoute.steps.length; i++) { const marker = (markerArray[i] = markerArray[i] || new google.maps.Marker()); marker.setMap(map); marker.setPosition(myRoute.steps[i].start_location); attachInstructionText( stepDisplay, marker, myRoute.steps[i].instructions, map ); } } function attachInstructionText(stepDisplay, marker, text, map) { google.maps.event.addListener(marker, "click", () => { // Open an info window when the marker is clicked on, containing the text // of the step. stepDisplay.setContent(text); stepDisplay.open(map, marker); }); }
/* Always set the map height explicitly to define the size of the div * element that contains the map. */ #map { height: 100%; } /* Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #floating-panel { position: absolute; top: 10px; left: 25%; z-index: 5; background-color: #fff; padding: 5px; border: 1px solid #999; text-align: center; font-family: "Roboto", "sans-serif"; line-height: 30px; padding-left: 10px; } #warnings-panel { width: 100%; height: 10%; text-align: center; }
<!DOCTYPE html> <html> <head> <title>Directions Service (Complex)</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&callback=initMap&libraries=&v=weekly" defer ></script> <!-- jsFiddle will insert css and js --> </head> <body> <div id="floating-panel"> <b>Start: </b> <select id="start"> <option value="penn station, new york, ny">Penn Station</option> <option value="grand central station, new york, ny"> Grand Central Station </option> <option value="625 8th Avenue, New York, NY, 10018"> Port Authority Bus Terminal </option> <option value="staten island ferry terminal, new york, ny"> Staten Island Ferry Terminal </option> <option value="101 E 125th Street, New York, NY"> Harlem - 125th St Station </option> </select> <b>End: </b> <select id="end"> <option value="260 Broadway New York NY 10007">City Hall</option> <option value="W 49th St & 5th Ave, New York, NY 10020"> Rockefeller Center </option> <option value="moma, New York, NY">MOMA</option> <option value="350 5th Ave, New York, NY, 10118"> Empire State Building </option> <option value="253 West 125th Street, New York, NY"> Apollo Theater </option> <option value="1 Wall St, New York, NY">Wall St</option> </select> </div> <div id="map"></div> &nbsp; <div id="warnings-panel"></div> </body> </html>

Create a starter application from sample

A skeleton starter application using TypeScript, Webpack, and Babel can be generated from this sample using one of the methods below.

Run Locally

Node.js is required to run this sample locally. Follow these instructions to install Node.js and NPM.

npm i -g '@googlemaps/js-samples'
googlemaps-js-samples init directions-complex DESTINATION_FOLDER

Run in Google Cloud Shell

Google Cloud Shell is an interactive shell environment for Google Cloud Platform that makes it easy for you to learn and experiment with GCP and manage your projects and resources from your web browser.

Run in Cloud Shell