Yos Riady software craftsman 🌱

A Gentle Introduction to Web Map APIs

I had the pleasure of teaching a technical workshop on Web Map APIs and how to build map-intensive applications such as Airbnb and Foursquare using OpenStreetMap, Mapbox, and Leaflet.

This post outlines the course material so it may be of use for others.

What is an API?

An API is an interface

API stands for Application Programming Interface and refers to a published list of functions that programmers can use in their own code to interact with another collection of code or libraries. It allows the functioning code in the background to be separated from how the code is called and used.

For example, an API that deals with tracking widgets may have a function calledwidgetLocation() that returns where a widget is currently located. As long as that function always returns the location in the same format, the underlying code for widgetLocation() can be changed and improved without breaking whatever program is using it.

What is a Web API?

A web API uses HTTP requests to get information from a remote server. There are a fair number of details, but essentially this means queries can made through where you type in URLs in your web browser. For example, here’s an example of a Reverse Geocoding API:

https://api.tiles.mapbox.com/v3/{mapid}/geocode/{lon},{lat}.json

Similar to a function call, by filling in the parameters and visiting the above URL, we can reverse geocode a pair of latitude and longitude values. Try going to the URL below:

https://api.tiles.mapbox.com/v3/examples.map-zr0njcqy/geocode/-73.989,40.733.json

Here is an excerpt of our result:

{
   query:[
      -73.989,
      40.733
   ],
   attribution:{
      mapbox-places:"<a href='https://www.mapbox.com/about/maps/' target='_blank'>&copy; Mapbox</a>"
   },
   results:[
      [
         {
            id:"address.70001044409997",
            bounds:[
               -73.99411799999999,
               40.73065899999999,
               -73.98307699999998,
               40.73531299999999
            ],
            lon:-73.988909,
            lat:40.733122,
            name:"124 E 13th St",
            type:"address"
         },
         {
            id:"mapbox-places.10001",
            bounds:[
               -74.04728500751165,
               40.68392799015035,
               -73.91058699000139,
               40.87764500765852
            ],
            lon:-74.006,
            lat:40.7143,
            name:"New York",
            type:"city"
         },
         {
            id:"zipcode.2254639497",
            bounds:[
               -73.99960399999998,
               40.722933,
               -73.97986399999999,
               40.73967299999999
            ],
            lon:-73.991023,
            lat:40.731226,
            name:"10003",
            type:"zipcode"
         },
         {
            id:"province.628083222",
            bounds:[
               -79.76241799999997,
               40.477398999999984,
               -71.77749099999998,
               45.015864999999984
            ],
            lon:-76.181929,
            lat:42.773969,
            name:"New York",
            type:"province"
         },
         {
            id:"country.4150104525",
            bounds:[
               -179.23023299999997,
               18.866158999999996,
               179.85968099999994,
               71.43776899999999
            ],
            lon:-98.958425,
            lat:36.778951,
            name:"United States",
            type:"country"
         }
      ]
   ]
}

As you can see, given a point location (latitude, longitude) we receive a JSON response of a readable address, in this case, E 13th Street, New York, New York.

You can also play around on your own with following Geocoding API:

https://api.tiles.mapbox.com/v3/{mapid}/geocode/{query}.json

Picking a Web Map API

There are a lot of Web Map APIs out there! Most have limited free usage quotas, and will start charging you beyond a certain point (25,000 map loads for Google Maps.) - Google Maps API - OpenStreetMap - Nokia Here - many others!

Additionally, the quality of maps across the different Map APIs are not the same. This is why some companies such as Foursquare use Leaflet, which is API provider-agnostic.

A Map API Workflow

In general, this is the general workflow of working with interactive maps and APIs:

  • Register for an API Key (where applicable)
  • Include the Map API’s CSS and Javascript files
  • Read the API documentation
  • Write map features using the API/library’s methods
  • PROFIT!!!

Introducing Leaflet

In this tutorial, we will create interactive maps using Leaflet.

What is Leaflet?

Leaflet is a Javascript library for interactive maps. Unlike Google Maps and other Map API providers, Leaflet is just a library, a layer of abstraction. It’s free to use, but doesn’t provide map imagery on its own — you have to choose a tile service to combine with it. You can roll your own tiles as well. This means you can easily switch between providers on the fly.

OpenStreetMap is the most popular data source among different tile providers, but there are providers that use other sources. It’s easy to implement this in Leaflet.

For more information on Leaflet, please check out the Leaflet FAQs.

Step 1: Initial Setup

Example: https://github.com/yosriady/orbital-leaflet/blob/master/step1.html

After creating an empty HTML document, we start by including the CSS and JS file for our Leaflet library. We include Leaflet’s CSS file https://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css in the head section of our document:

Leaflet

Next, we include Leaflet’s JS file https://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js near the end of our HTML document, as well as preparing a script area for our map initialization code:

Leaflet

Finally, we’ll create an HTML div where our interactive map will be displayed. In our map initialization code, we will refer to the HTML id of this element (“map”) to specify that this element is the map “container.”

Leaflet

Open up your html file on your web browser, open up the Developer Console and you should see no errors.

Step 2: A Basic map

Example: https://github.com/yosriady/orbital-leaflet/blob/master/step2.html

Next, we’ll write some Javascript code to initialize and render a basic map on our webpage. At this point in the tutorial, don’t worry if the code seem unfamiliar. When using third-party libraries and APIs, you will often need to pore through the API’s documentation. Fortunately for us, Leaflet is one of the best documented Javascript libraries I’ve ever come across. In this tutorial, I will link to the relevant API references at each step.

Leaflet > The Leaflet API Reference. The most important sections are Map, UI Layers, Basic Types, and Events.

First, we’ll initialize the map and set its view to our chosen geographical coordinates and a zoom level.

Leaflet > L.map API Reference > L.map.setView API Refence

Essentially, in the code above, we are specifying that our map’s container will have the HTML ID map, starts centered at LatLng coordinates 51.505, -0.09, and with zoom level 13. Be sure to check the Leaflet Map Options documentation for more options.

Next we’ll add a tile layer to add to our map, in this case it’s an OpenStreetMap tile layer at the following URL: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png. Creating a tile layer usually involves setting the URL template for the tile images, the attribution text and the maximum zoom level of the layer. We then add this tileLayer to our Map object.

Leaflet > L.tileLayer API Reference

Open up your HTML file in your web browser, and check that the Developer Console displays no errors. You should now see a basic map displayed, centered at NUS [1.296643, 103.776394].

Leaflet

Great success! We’ve successfully displayed a basic map! However, as you can probably tell, it’s not a great looking map. OpenStreetMap data is accurate, but the tileset is not the prettiest.

Step 3: Using an external tileset (MapQuest Open)

The issue on the initial use of OpenStreetMap is it’s ugly, so we should have a look at a different map tile provider. Leaflet makes this very easy to implement just by changing one URL.

What are tile providers? A tile provider is a source of the tiles that Leaflet uses to present a map. Because there are many unique requirements for maps there are a large number of variations of tile servers that apply different formatting and styling to the geographic information.

Check out this example with half a hundred different layers to choose from. Popular commercial options, free up to a particular number of requests, include MapBox, Bing Maps (using a plugin), Esri ArcGIS (official plugin) and Nokia Here. A notable exception is MapQuest Open, which is free for any number of requests. For this tutorial, we are using MapQuest Open.

Always be sure to read the terms of use of a chosen tile provider, know its limitations, and attribute it properly in your app.

For this tutorial, we are using MapQuest Open - OpenStreetMap data layered using MapQuest color schemes. I’ve found that this tileset provides the most accurate and best looking map, but feel free to explore on your own.

To use MapQuest Open, we will remove our old OpenStreetMap TileLayer code and replace it with the following:

Leaflet

This time, we’re using the OpenMapQuest tile provider. Similar to our initial TileLayer, creating a TileLayer involves setting the URL template for the tile images, the attribution text and the maximum zoom level of the layer. We then add this tileLayer to our Map object.

Refresh your HTML file on your web browser, and you should see a map using a different tileset! Note that OpenMapQuest is powered by OpenStreetMap, but is using the MapQuest color scheme. Hurrah!

For more information on other tile providers you can use, check out the leaflet-providers extension and this Github gist on configurations for different providers.

Step 4: Adding markers

A basic map on its own is pretty cool, but we can do more useful things. You can easily add other objects to your map, including markers, polylines, polygons, circles, and popups. In this part of the tutorial, we are going to add a marker to our map.

Leaflet > L.marker API reference

Leaflet > L.latLng API reference

Referring to the documentation, we see that the Marker object takes in a required LatLng object, which represents a geographical point with a certain latitude and longitude. LatLong objects takes two required parameters, a latitude, and longitude. In our code, we add the following lines:

Leaflet

Once added, you should see a marker appear in our map. Hurrah!

Leaflet

For extra credit, create a new marker by executing the marker creation code in the Web Console.

Markers can take in an optional options parameter, which allows you to customize the icon, whether it is clickable or draggable, its opacity and more. For full details on marker options, check out the Leaflet Marker documentation.

Note that you can create LatLng objects using a shorthand. All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so the line below is equivalent:

Leaflet

Adding a circle is the same (except for specifying the radius in meters as a second argument), but lets you control how it looks by passing options as the last argument when creating the object:

Leaflet

Adding polygons:

Leaflet

Step 5: Adding popups

Popups are usually used when you want to attach some information to a particular object on a map. Let’s see what it looks like on our map:

Leaflet

To create a popup, we need to instantiate a Leaflet popup object:

Leaflet > L.popup reference

Now, let’s attach our popup to a marker click event using the marker bindPopup method:

Leaflet > bindPopup reference

Now, the popup should toggle between visible and invisible when the marker is clicked. Hurrah! You have just handled your first event. Internally, bindPopup handles and associates any click events on the marker to showing and hiding the popup. We’ll go into more detail in the next section.

Step 6: Handling events

You can easily listen to and respond to different user events within the map. An event can be a mouse click, drag, and many others. Events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map fire event).

Leaflet > An excerpt of the different events you can detect

Each object has its own set of events — see documentation for details. The first argument of the listener function is an event object — it contains useful information about the event that happened. For example, map click event object (e in the example below) has latlng property which is a location at which the click occurred. For more details on event objects, check out Event Objects. You can view the event objects in the Developer Console by using console.log, as shown below:

Leaflet

Likewise, let’s attach a click event handler for our marker:

Leaflet

Next, let’s display a popup instead of using the ugly Javascript alert box:

Leaflet

As you can see, we instantiate a new popup object, set its parameters, and called its openOn method to display the popup on click. You can create any number of objects and do pretty much anything within your event handlers.

Step 7: Geolocation

Leaflet

Step 8: Routing

We will be using a Leaflet plugin to handle routing. Please see the step8 code in the workshop repo for more details.

Leaflet

Project Time

In this section, we will create a map that allows users to leave notes on an interactive map. You can view a live demo of this project here

Leaflet

Use case: Sharing places in NUS conducive for studying, napping, or both!

We will not cover how to save the routes into your Datastore due to time constraints. You will get to figure that out at your own leisure. You will need to: Design your Javascript objects to encapsulate points of interest Design GAE Datastore Entities (to keep the Marker and other user-specific information) Code a “serializer” that stores your JS objects into the Datastore as Datastore entities

Here are some additional features you can add to the project as an exercise at your own leisure: Double click to delete a marker Allow users to edit the marker content Geocode the Lat, Lng values into an address using a Geocoding API Geolocate the user’s current location

You will find the Leaflet API Reference extremely helpful.

Summary

You now know everything you need to start building mapping-enabled applications. Now go forth and have fun building interactive maps!

Author

Yos is a software craftsman based in Singapore.

📬 Subscribe to my newsletter

Get notified of my latest articles by providing your email below.


Going Serverless book

Interested to find out more about serverless? Going Serverless teaches you how to build scalable applications with the Serverless framework and AWS Lambda. You'll learn how to design, develop, test, deploy, and secure Serverless applications from planning to production.

Learn More →