Learn how to find a route and directions.
The ArcGIS Routing service
In this tutorial, use the MapLibre ArcGIS plugin to display a map and ArcGIS REST JS to access the Routing service. You click on the map to get an origin
Prerequisites
You need an ArcGIS Location Platform or ArcGIS Online account.
Steps
Get the starter app
Select a type of authentication and follow the steps to create a new app.
Choose API key authentication if you:
- Want the easiest way to get started.
- Want to build public applications
A public application is an application that allows anonymous access without requiring users to sign in with an ArcGIS account. It supports API key or app authentication. that access ArcGIS Location ServicesArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Static Maps service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. and secure itemsAn item, also known as a content item, is a resource stored in a portal such as a web map, hosted layer, style, script tool, file, or notebook. . - Have an ArcGIS Location Platform or ArcGIS Online account.
Choose user authentication if you:
- Want to build private applications.
- Require application users to sign in with their own ArcGIS account
An ArcGIS account is an identity with a user type and set of privileges that can access specific ArcGIS products, tools, APIs, services, and resources. The main account types that can be used for development are an ArcGIS Location Platform account, ArcGIS Online account, and ArcGIS Enterprise account. ArcGIS Location Platform and ArcGIS Online accounts are also associated with a subscription. and access resources their behalf. - Have an ArcGIS Online account.
To learn more about both types of authentication, go to Authentication.
Set up authentication
Set developer credentials
Use the API key or OAuth developer credentials
Add references to ArcGIS REST JS
-
In the
<headelement, add references to the ArcGIS REST JS library.> Use dark colors for code blocks <head> <title>MapLibre ArcGIS tutorial: Find a route and directions</title> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> <!-- Load MapLibre GL JS from CDN --> <script src="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script> <link href="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css" rel="stylesheet"> <!-- Load MapLibre ArcGIS from CDN --> <script src="https://unpkg.com/@esri/maplibre-arcgis@1.3.0/dist/umd/maplibre-arcgis.min.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-request@4/dist/bundled/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-routing@4/dist/bundled/routing.umd.js"></script> <style> html, body, #map { padding: 0; margin: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #323232; } </style> </head>
Update the map
An arcgis/navigation basemap style
-
Update the basemap and the map initialization to center on location
[-79.3832,43.6532], Toronto.Use dark colors for code blocks Copy /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URI", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; const map = new maplibregl.Map({ container: "map", // the id of the div element zoom: 12, // starting zoom center: [-79.3832, 43.6532] // Toronto }); const basemapStyle = maplibreArcGIS.BasemapStyle.applyStyle(map, { style: "arcgis/navigation", token: accessToken });
Add end point layers
To display circles for the start and end of the route, you will two circle layers
-
Create a function called
add.Circle Layers Use dark colors for code blocks const map = new maplibregl.Map({ container: "map", // the id of the div element zoom: 12, // starting zoom center: [-79.3832, 43.6532] // Toronto }); const basemapStyle = maplibreArcGIS.BasemapStyle.applyStyle(map, { style: "arcgis/navigation", token: accessToken }); function addCircleLayers() { } -
Add a GeoJSON source for the start and end, with ids
route-startandroute-end. Set thedataattribute of each source to be an empty FeatureCollection.This source will later contain the geometry information of the start or end point that the user has selected. For now, you can simply provide it with an empty piece of GeoJSON: a feature collection that contains no features.
Use dark colors for code blocks function addCircleLayers() { map.addSource("start", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addSource("end", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); } -
Add a layer of type
circlefor the start and end, connected to those sources. Use thecircle-colorpaint property to make the start circle white and the end circle black.Each layer will display the data in its source. Since there is no data in those sources for now, nothing will display yet.
Use dark colors for code blocks function addCircleLayers() { map.addSource("start", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addSource("end", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "start-circle", type: "circle", source: "start", paint: { "circle-radius": 6, "circle-color": "white", "circle-stroke-color": "black", "circle-stroke-width": 2 } }); map.addLayer({ id: "end-circle", type: "circle", source: "end", paint: { "circle-radius": 7, "circle-color": "black" } }); }
Add a load event handler
At this stage, the layers have not been added to the map. It is important to wait for the map to finish loading before adding the layers.
-
Add an event handler to the map
loadevent. Call theaddfunction.Circle Layers Use dark colors for code blocks map.addLayer({ id: "end-circle", type: "circle", source: "end", paint: { "circle-radius": 7, "circle-color": "black" } }); } map.on("load", () => { addCircleLayers(); addRouteLayer(); });
Add a click handler
You will click twice to set a start and end for the route. The first click will update the start sourceend source. To set the GeoJSONmap.get to get the Source, then call set.
You use a click event handler to respond to these clicks.
The object passed to the click event contains several useful properties, including:
lng: the map location where the click took place.Lat point: the screen location in pixels where the click took place.original: the DOM event, which contains information about modifier keys.Event
For more information, see the MapLibre GL JS documentation.
-
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.Use dark colors for code blocks map.on("load", () => { addCircleLayers(); addRouteLayer(); }); let currentStep = "start"; let startCoords, endCoords; -
Add a
clickevent handler to the map. Use thelngproperty of the event parameter to create a GeoJSONLat Pointobject.Use dark colors for code blocks let currentStep = "start"; let startCoords, endCoords; map.on("click", (e) => { const coordinates = e.lngLat.toArray(); const point = { type: "Point", coordinates }; }); -
Use
map.getand theSource setmethod to update the correct source with the GeoJSON object.Data Use dark colors for code blocks map.on("click", (e) => { const coordinates = e.lngLat.toArray(); const point = { type: "Point", coordinates }; if (currentStep === "start") { map.getSource("start").setData(point); startCoords = coordinates; const empty = { type: "FeatureCollection", features: [] }; map.getSource("end").setData(empty); map.getSource("route").setData(empty); endCoords = null; currentStep = "end"; } else { map.getSource("end").setData(point); endCoords = coordinates; currentStep = "start"; } }); -
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
The route object that will be retrieved is a GeoJSONLine object. To display it, you define a GeoJSON source
-
Create a
addfunction. Inside, add a source of typeRoute Layer geojsonwith idroute. Set itsdataattribute to be an emptyFeature.Collection Use dark colors for code blocks map.addLayer({ id: "end-circle", type: "circle", source: "end", paint: { "circle-radius": 7, "circle-color": "black" } }); } function addRouteLayer() { map.addSource("route", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); } -
Add a layer of type
linewith idroute-line. Set its source to beroute, and give it width, color and opacity attributes.This source will later contain the geometry information of the route between points that the user has selected. For now, you can simply provide it with an empty piece of GeoJSON: a feature collection that contains no features.
The layer will display the source. Since there is no data in the source for now, nothing will display yet.
Use dark colors for code blocks function addRouteLayer() { map.addSource("route", { type: "geojson", data: { type: "FeatureCollection", features: [] } }); map.addLayer({ id: "route-line", type: "line", source: "route", paint: { "line-color": "hsl(205, 100%, 50%)", "line-width": 4, "line-opacity": 0.6 } }); }
Get the route
To find the route, you use ArcGIS REST JSsolve function to access the route service
To update the route source with the result, get the Source with map.get to get the Source, then call set.
-
Create a function called
update. Inside, create a newRoute Apito access the route serviceKey Manager A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. . Callsolvewith the two sets of coordinates as aRoute stopsarray.Use dark colors for code blocks paint: { "line-color": "hsl(205, 100%, 50%)", "line-width": 4, "line-opacity": 0.6 } }); } function updateRoute() { const authentication = arcgisRest.ApiKeyManager.fromKey(accessToken); arcgisRest .solveRoute({ stops: [startCoords, endCoords], endpoint: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve", findBestSequence: false, authentication }) } -
Create a response handler. Inside, use the
setmethod to update theData routesource's geometry from the response'sroutes.geojsonproperty.Use dark colors for code blocks arcgisRest .solveRoute({ stops: [startCoords, endCoords], endpoint: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve", findBestSequence: false, authentication }) .then((response) => { map.getSource("route").setData(response.routes.geoJson); }) -
Add an error handler. Show a message and log a message if there is a problem.
Use dark colors for code blocks .then((response) => { map.getSource("route").setData(response.routes.geoJson); }) .catch((error) => { console.error(error); alert("There was a problem using the route service. See the console for details."); });
Update the click handler
If the start and end coordinates have been set by the user, you can now call your update function.
-
Check that the start and end coordinates have been set. Then call
update.Route Use dark colors for code blocks map.on("click", (e) => { const coordinates = e.lngLat.toArray(); const point = { type: "Point", coordinates }; if (currentStep === "start") { map.getSource("start").setData(point); startCoords = coordinates; const empty = { type: "FeatureCollection", features: [] }; map.getSource("end").setData(empty); map.getSource("route").setData(empty); endCoords = null; currentStep = "end"; } else { map.getSource("end").setData(point); endCoords = coordinates; currentStep = "start"; } if (startCoords && endCoords) { updateRoute(startCoords, endCoords); } });
Show directions
The data returned from the route service<div element. You will populate this with data drawn from the directions attribute of the response.
-
In the
<body, add a> <divelement with an id of> directions.Use dark colors for code blocks <body> <div id="map"></div> <div id="directions">Click on the map to create a start and end for the route.</div> -
In the
<stylesection, style the> #directionselement withabsoluteposition so it sits in front of the map, and a fixed width and height.Use dark colors for code blocks <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> -
In the query response handler, set the contents of the
<divelement using the> directionsattribute. Join thetextattributes of each element of thefeaturesarray to make the HTML contents of the<divelement. Use> <brtags between each line to create a line break.> The
directionselement is an array where each element corresponds to one route. Itsfeaturesattribute is an array with information about each step on the route, including the length of the maneuver, the kind of maneuver, and the text that should be shown to the user.Use dark colors for code blocks .then((response) => { map.getSource("route").setData(response.routes.geoJson); const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>"); document.getElementById("directions").innerHTML = directionsHTML; }) .catch((error) => { console.error(error); alert("There was a problem using the route service. See the console for details."); });
Run the app
Run the app.
When the map displays, you should be able to click on it once to create an origin point and again to create a destination point. The Routing service should then display the resulting route and turn-by-turn directions.What's next?
Learn how to use additional location services in these tutorials:


