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
- 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.
Go to your dashboard to get an API key.
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
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
.
Update the basemap and the map initialization to center on location
[-79.3832,43.6532]
, Toronto.Change line Change 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.
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>
Inside the function, create a new
Vector
layer for thestartLayer
. Use aCircle
style to make a white circle with black stroke. Add it to the map withmap.addLayer
. Do the same forendLayer
, 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>
Add a map load event handler by adding a
then
function to theolms
function. Inside, calladdCircleLayers
.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.
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 aGeoJSON
feature format and store it to ageojson
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>
Add a
click
event handler to the map. Inside, transform thecoordinate
property of the event object to latitude and longitude and store it in a variable. Use this to create a GeoJSONPoint
.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>
Use
setSource
on the current layer to set a newVector
source. Use thereadFeatures
method of thegeojson
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>
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 theclear
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>
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.
Create an
addRouteLayer
function. Inside, define arouteLayer
with a blue stroke, 4 pixel width and medium opacity. Usemap.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