Find a route and directions

Learn how to find a route and directions with the route service.

Routing is the process of finding the path from an origin to a destination in a street network. You can use the route service to find routes, get driving directions, calculate drive times, and solve complicated, multiple vehicle routing problems. To create a route, you typically define a set of stops (origin and one or more destinations) and use the service to find a route with directions. You can also use a number of additional parameters such as barriers and mode of travel to refine the results.

In this tutorial, you use ArcGIS REST JS to access the routing service to get route. You click on the map to get an origin and destination that are used to get a route and directions from the route service. The directions are also displayed on the map.

Prerequisites

You need a free ArcGIS developer account to access your dashboard and API keys. The API key must be scoped to access the services used in this tutorial.

Steps

Create a new pen

  1. To get started, either complete the Display a map tutorial or .

Set the API key

To access ArcGIS location services, you need an API key.

  1. Go to your dashboard to get an API key.

  2. In CodePen, update apiKey to use your key.

    Change line
        
    const apiKey = "YOUR-API-KEY";
    const basemapId = "ArcGIS:Streets";
    const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    olms(map, basemapURL);
    

Add references to ArcGIS REST JS

  1. In the <head> element, add references to the ArcGIS REST JS library.

    Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>

Update the map

A navigation basemap layer is typically used in geocoding and routing applications. Update the basemap layer to use ArcGIS:Navigation.

  1. Update the basemap and the map initialization to center on location [-79.3832,43.6532], Toronto.

    Change lineChange line
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>

Add end point layers

To display circles for the start and end of the route, you will create two circle vector layers.

  1. Define variables to hold the start layer, end layer, and the route layer that you will create. Create a function called addCircleLayers.

    Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  2. Inside the function, create a new Vector layer for the startLayer. Use a Circle style to make a white circle with black stroke. Add it to the map with map.addLayer. Do the same for endLayer, but with a black fill and white stroke.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  3. Add a map load event handler by adding a then function to the olms function. Inside, call addCircleLayers.

    Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>

Add a click handler

You need a start (origin) and end (destination) to create a route. The first click will set a source for the startLayer and the second click will set a source for the endLayer. You will use a GeoJSON feature format to set these sources. Use a click event handler to respond to these clicks.

  1. Add a variable to store whether the next click will be for the start or end of the route. Set it initially to start. Add a variable to store the coordinates for each end. Create a GeoJSON feature format and store it to a geojson variable.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  2. Add a click event handler to the map. Inside, transform the coordinate property of the event object to latitude and longitude and store it in a variable. Use this to create a GeoJSON Point.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  3. Use setSource on the current layer to set a new Vector source. Use the readFeatures method of the geojson feature format you defined earlier to set the data. Save the coordinates for later use.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  4. After setting the start point source, check if there are already end coordinates stored, indicating the user is resetting the route. If so, clear the endCoords variable and the clear method to remove the end point layer features.

    Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color: "hsl(205, 100%, 50%)", width: 4, opacity: 0.6 })
              })
            });
    
            map.addLayer(routeLayer);
          }
    
          function updateRoute() {
            const authentication = new arcgisRest.ApiKey({
              key: apiKey
            });
            arcgisRest
    
              .solveRoute({
                stops: [startCoords, endCoords],
                authentication
              })
    
              .then((response) => {
    
                routeLayer.setSource(
                  new ol.source.Vector({
                    features: geojson.readFeatures(response.routes.geoJson)
                  })
                );
    
                const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>");
                document.getElementById("directions").innerHTML = directionsHTML;
                document.getElementById("directions").style.display = "block";
    
              })
    
              .catch((error) => {
                alert("There was a problem using the geocoder. See the console for details.");
                console.error(error);
              });
    
          }
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL)
    
    
            .then(function (map) {
              addCircleLayers();
    
              addRouteLayer();
    
            });
    
        </script>
    
      </body>
    
    </html>
  5. At the top right, click Run. You should be able to click in two places to set a white circle for the start, and a black circle for the end.

Add route layer

To display the route line that you will receive from the routing service, you will create another Vector layer.

  1. Create an addRouteLayer function. Inside, define a routeLayer with a blue stroke, 4 pixel width and medium opacity. Use map.addLayer to add it to the map.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                                                                                                       
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find a route and directions</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
    
          #directions {
            position: absolute;
            width: 30%;
            max-height: 50%;
            right: 20px;
            top: 20px;
            overflow-y: auto; /* Show a scrollbar if needed */
            background: white;
            font-family: Arial, Helvetica, Verdana;
            line-height: 1.5;
            font-size: 14px;
            padding: 10px;
          }
    
        </style>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-routing@3.0.0/dist/umd/routing.umd.js"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <div id="directions">Click on the map to create a start and end for the route.</div>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-79.3832,43.6532]), // Toronto
    
            zoom: 13
          });
          map.setView(view);
    
          let startLayer, endLayer, routeLayer;
          function addCircleLayers() {
    
            startLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 6,
                  fill: new ol.style.Fill({ color: "white" }),
                  stroke: new ol.style.Stroke({ color: "black", width: 2 })
                })
              })
            });
            map.addLayer(startLayer);
            endLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 7,
                  fill: new ol.style.Fill({ color: "black" }),
                  stroke: new ol.style.Stroke({ color: "white", width: 2 })
                })
              })
            });
    
            map.addLayer(endLayer);
    
          }
    
          let currentStep = "start";
          let startCoords, endCoords;
    
          const geojson = new ol.format.GeoJSON({
            defaultDataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          });
    
          map.on("click", (e) => {
    
            const coordinates = ol.proj.transform(e.coordinate, "EPSG:3857", "EPSG:4326");
            const point = {
              type: "Point",
              coordinates
            };
    
            if (currentStep === "start") {
    
              startLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              startCoords = coordinates;
    
              // clear endCoords and route if they were already set
              if (endCoords) {
                endCoords = null;
                endLayer.getSource().clear();
    
                routeLayer.getSource().clear();
    
                document.getElementById("directions").innerHTML = "";
                document.getElementById("directions").style.display = "none";
    
              }
    
              currentStep = "end";
            } else {
    
              endLayer.setSource(
                new ol.source.Vector({
                  features: geojson.readFeatures(point)
                })
              );
              endCoords = coordinates;
              currentStep = "start";
    
              updateRoute(startCoords, endCoords);
    
            }
    
          });
    
          function addRouteLayer() {
            routeLayer = new ol.layer.Vector({
              style: new ol.style.Style({
                stroke: new ol.style.Stroke({ color