Overview

You will learn: how to find the optimal route and directions for multiple stops with the ArcGIS Route service.

The ArcGIS Routing and Network Analytics Services can find routes, get driving directions, calculate drive times, and solve complicated multiple vehicle routing problems (VRP). If you would like to create an application that can find driving directions and create an optimized route, you can use the RouteTask class to create a route, provide stop locations, and optionally barriers and the mode of transportation. The service will return a route with directions. Once you have the results you can add the route to a map, display turn-by-turn directions, or integrate them further into your application. To learn more about the capabilities of the underlying service, please visit the REST tutorials.

In this tutorial you will learn how to use a routing service to calculate an optimal route between two places. You will create a start and a finish point by tapping on the map.

Steps

Create a starter app

  1. Go to the JavaScript Starter App.

  2. In CodePen, click Fork and save the pen as ArcGIS Tutorials: Get a route and directions.

Change the basemap

  1. In the main function, update the existing code to use the streets-navigation-vector basemap.

      var map = new Map({
        basemap: "streets-navigation-vector"
      });
    

Create the route task

  1. In the require statement, add the RouteTask, RouteParameters, FeatureSet and Graphic modules.

    require([
      "esri/Map",
      "esri/views/MapView",
      //*** ADD ***//
      "esri/tasks/RouteTask",
      "esri/tasks/support/RouteParameters",
      "esri/tasks/support/FeatureSet",
      "esri/Graphic"
    ], function(Map, MapView, RouteTask, RouteParameters, FeatureSet, Graphic) {
    
  2. In the main function, create a RouteTask and reference the ArcGIS Route service.

      var routeTask = new RouteTask({
         url: "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World"
      });
    

Get a start and finish point

Before you can execute the route task you need to assemble the input parameters. There are a number of parameters you can provide such as stops, barriers and the preferred order, but at a minimum you need to provide the start and finish location.

  1. In the main function, create click handler and a addGraphic function to add graphics when the view is clicked. Create a simple white marker for the start and a black marker for the finish location. After two graphics have been created, call the getRoute function to execute the route task. This will be completed in the next step.

      view.on("click", function(event){
        if (view.graphics.length === 0) {
          addGraphic("start", event.mapPoint);
        } else if (view.graphics.length === 1) {
          addGraphic("finish", event.mapPoint);
          // Call the route service
          getRoute();
        } else {
          view.graphics.removeAll();
          addGraphic("start",event.mapPoint);
        }
      });
    
      function addGraphic(type, point) {
        var graphic = new Graphic({
          symbol: {
            type: "simple-marker",
            color: (type === "start") ? "white" : "black",
            size: "8px"
          },
          geometry: point
        });
        view.graphics.add(graphic);
      }
    

Execute the route task

The last step is to call the service and add the route to the map.

  1. Write a new getRoute function to create the RouteParameters and pass in the stops graphics collected eariler. Also set returnDirections to true to ensure the text directions are returned as well (see challenge). Call the solve method and when the task returns, extract the route from the RouteResult and add the route to the map with a blue symbol.

      function getRoute() {
        // Setup the route parameters
        var routeParams = new RouteParameters({
          stops: new FeatureSet({
            features: view.graphics.toArray() // Pass the array of graphics
          }),
          returnDirections: true
        });
        // Get the route
        routeTask.solve(routeParams).then(function(data) {
          // Display the route
          data.routeResults.forEach(function(result) {
            result.route.symbol = {
              type: "simple-line",
              color: [5, 150, 255],
              width: 3
            };
            view.graphics.add(result.route);
          });
        });
      }
    
  2. Run the app and click on two locations to generate a route.

NOTE: If you would like to prevent the authentication dialog from appearing, try the challenge step below.

Congratulations, you're done!

Your app should look something like this.

Challenge

Prevent the authentication dialog from appearing

If you want to access the ArcGIS Routing service directly and prevent the application from prompting the user for authentication, you can use a service proxy.

  1. Go to the Set up authenticated services lab and create a proxy to access the ArcGIS Routing and Directions Service.

  2. In the dashboard, copy the Routing and Directions proxy URL and update the application code.

     var routeTask = new RouteTask({
       //*** ADD ***//
       url: "https://utility.arcgis.com/usrsvcs/appservices/<your-id>/rest/services/World/Route/NAServer/Route_World/solve"
     });
    
  3. Run the application again and it shouldn't prompt the user to sign in.

Show the directions

Display the directions for the route by adding the turn-by-turn directions and distance in miles to the map after the route draws.

NOTE: This is a just simple implementation to get you started, but if you want to see a more interactive application that has interactive route segments, directions and arrows, try the Driving directions lab.

  function getRoute() {
    // Setup the route parameters
    var routeParams = new RouteParameters({
      stops: new FeatureSet({
        features: view.graphics.toArray() // Pass the array of graphics
      }),
      returnDirections: true
    });
    // Get the route
    routeTask.solve(routeParams).then(function(data) {
      // Display the route
      data.routeResults.forEach(function(result) {
        result.route.symbol = {
          type: "simple-line",
          color: [5, 150, 255],
          width: 3
        };
        view.graphics.add(result.route);
      });

      //*** ADD ***//

      // Display the directions
      var directions = document.createElement("ol");
      directions.classList = "esri-widget esri-widget--panel esri-directions__scroller";
      directions.style.marginTop = 0;
      directions.style.paddingTop = "15px";

      // Show the directions
      var features = data.routeResults[0].directions.features;
      features.forEach(function(result,i){
        var direction = document.createElement("li");
        direction.innerHTML = result.attributes.text + " (" + result.attributes.length.toFixed(2) + " miles)";
        directions.appendChild(direction);
      });

      // Add directions to the view
      view.ui.empty("top-right");
      view.ui.add(directions, "top-right");
    });
  }
Content