Skip to content

How to get Directions in JavaScript from the Stadia Maps Geospatial API

This tutorial will walk you through the process of getting directions using the Stadia Maps Geospatial APIs. We'll get directions between two points from the Stadia Maps Geospatial API using vanilla JavaScript, and visualize the route using MapLibre GL JS.

Tip

We've done our best to make useful examples that you can play with in JSFiddle, but if you're itching to integrate with your existing code locally, read on!

If you're running a local development server on localhost or 127.0.0.1, you should be able to copy+paste the code into your existing app—everything should just work ™! Before deploying to a live web server, you will need to sign up for a Stadia Maps account and add your domain or set up an API key in the client dashboard.

You can find out more about how we authenticate requests in the Authentication & Limits documentation.

A simple route function

Let's start by writing a function that gets a route from the API. We've written all the boilerplate, so you can focus on the parameters.

function simple_route(start_lat, start_lon, end_lat, end_lon, costing, callback) {
  // Build a request body for the route request
  var body = {
    "locations": [
      {
        "lat": start_lat,
        "lon": start_lon,
        "type": "break"
      },
      {
        "lat": end_lat,
        "lon": end_lon,
        "type": "break"
      }
    ],
    "costing": costing,
  };

  var oReq = new XMLHttpRequest();
  oReq.open("POST", "https://api.stadiamaps.com/route/v1", true);
  oReq.onload = function() { 
    var jsonData = JSON.parse(this.responseText);

    callback(jsonData);
  };
  oReq.onerror = function(e) {
      console.error(e);
  }
  oReq.onabort = function(e) {
      console.error(e);
  }

  oReq.send(JSON.stringify(body));
}

The first four parameters (start_lat, start_lon, etc.) are the coordinates you want the route to start and end at.

The next argument is the costing model. This is a fancy term that essentially means mode of travel. The most common values are auto, bicycle, and pedestrian.

Tip

Our API reference have a list of all possible costing models (look at the costingModel schema) and other parameters available when making a route request.

Finally, the function takes a callback argument. This is a simple JavaScript function that does something with the response (a simple JavaScript object).

The following code will get driving directions from (66.543333, 25.8475) to (59.437222, 24.745278) and print the response to the console.

simple_route(66.543333, 25.8475, 59.437222, 24.745278, "auto", function(response) {
    console.log(response);
});

Tip

We won't go too deep into the all the response fields in this tutorial, but we encourage you to experiment with a simple callback like the above to see what the data looks like. The API reference covers what each field means (see the routeResponse schema).

Polyline decoding

The API returns the shape of the route as an encoded polyline. To visualize this on a map, we need to decode this back into a set of coordinates. For this tutorial, we'll decode the polyline using the Mapbox polyline library. We opt to decode it as GeoJSON, since this the easiest to work with in MapLibre GL JS.

polyline.toGeoJSON(shape, 6)

Pulling it all together

Now that we have all the data we need, let's pull it all together into a web page! Click the button below to experiment with it in JSFiddle.

Edit in JSFiddle
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Vector Map Demo</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <script type="text/javascript" src="//unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.js"></script>
    <link href="//unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css" rel="stylesheet" />

    <!-- We'll load the polyline library from unpkg for convenience in this tutorial for simplicity -->
    <script type="text/javascript" src="https://unpkg.com/@mapbox/polyline"></script>

    <style type="text/css">
      body {
        margin: 0;
        padding: 0;
      }

      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="text/javascript">
      function simple_route(start_lat, start_lon, end_lat, end_lon, costing, callback) {
        // Build a request body for the route request
        var body = {
          "locations": [
            {
              "lat": start_lat,
              "lon": start_lon,
              "type": "break"
            },
            {
              "lat": end_lat,
              "lon": end_lon,
              "type": "break"
            }
          ],
          "costing": costing,
        };

        var oReq = new XMLHttpRequest();
        oReq.open("POST", "https://api.stadiamaps.com/route/v1", true);
        oReq.onload = function() { 
          var jsonData = JSON.parse(this.responseText);

          callback(jsonData);
        };
        oReq.onerror = function(e) {
            console.error(e);
        }
        oReq.onabort = function(e) {
            console.error(e);
        }

        oReq.send(JSON.stringify(body));
      }

      var map = new maplibregl.Map({
        container: "map",
        style: "https://tiles.stadiamaps.com/styles/alidade_smooth.json",  // Style URL; see our documentation for more options
        center: [12, 53],  // Initial focus coordinate
        zoom: 4
      });

      // MapLibre GL JS does not handle RTL text by default,
      // so we recommend adding this dependency to fully support RTL rendering. 
      maplibregl.setRTLTextPlugin("https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.1/mapbox-gl-rtl-text.js");

      // Add zoom and rotation controls to the map.
      map.addControl(new maplibregl.NavigationControl());

      // Find a route between Santa's Village and Tallinn,
      // where a legend claims the first Christmas tree may
      // have appeared: https://www.visitestonia.com/en/why-estonia/the-tale-of-tallinns-most-famous-christmas-tree.
      // We'll assume that Santa's Reindeer are on strike,
      // so he has to drive a truck. (In case you're wondering
      // how he gets across the water, there is a ferry involved.)
      simple_route(66.543333, 25.8475, 59.43995, 24.73715, "truck", function(response) {
        // Construct a bounding box in the sw, ne format required by MapLibre. Note the lon, lat order.
        var sw = [response.trip.summary.min_lon, response.trip.summary.min_lat];
        var ne = [response.trip.summary.max_lon, response.trip.summary.max_lat];

        // Zoom to the new bounding box to focus on the route,
        // with a 50px padding around the edges. See https://maplibre.org/maplibre-gl-js-docs/api/map/#map#fitbounds.
        map.fitBounds([sw, ne], {padding: 50});

        // For each leg of the trip...
        response.trip.legs.forEach(function(leg, idx) {
          // Add a layer with the route polyline as an overlay on the map
          var layerID = "leg-" + idx;  // Unique ID with request ID and leg index
          // Note: Our polylines have 6 digits of precision, not 5
          var geometry = polyline.toGeoJSON(leg.shape, 6);
          map.addLayer({
            "id": layerID,
            "type": "line",
            "source": {
              "type": "geojson",
              "data": {
                "type": "Feature",
                "properties": {},
                "geometry": geometry
              }
            },
            "layout": {
              "line-join": "round",
              "line-cap": "round"
            },
            "paint": {
              "line-color": "#0072ce",
              "line-opacity": 0.3,
              "line-width": 5
            }
          });
        });
      });
    </script>
  </body>
</html>

You're now able to use the Stadia Maps Geospatial APIs to get routes, parse summary information about the route, and visualize it on a map! This should give you a good foundation on which to build more complex routing applications for the web using the Stadia Maps Geospatial APIs.