Making a web map with Leaflet

At the last CenTexGIS quarterly meeting, I gave a talk on Leaflet: the slides from that talk are available here.

During the talk, I briefly showed what you might do to create a simple Leaflet map, using open City of Austin data to show the location of all libraries in Austin. CenTexGIS members (and anyone else interested): here is the detailed walkthrough of that demo that I promised. There's nothing fancy here, but it's a good starting point, especially if you've never made a web map at all.

To recap:

What was Leaflet, again?

Leaflet is a tool you can use to make your own web maps. It's a JavaScript tool, so you need to write a little JavaScript & HTML to make a map.

And what about Mapbox?

Mapbox is a collection of open source web mapping tools. It a bit like a toolbox that holds a lot of cool things for maps on the web: cartography & aerial imagery, developer tools, maps for mobile apps, and more.

How are Leaflet & Mapbox related?

Leaflet (a particular tool) is not Mapbox (a company + collection of tools), but pieces of Mapbox work very well with Leaflet. For this demo map, I used the Mapbox Editor to create a pretty basemap, which I then stuck under City of Austin libraries data on the web map.

What about the whole 'open source' thing?

Leaflet is an open source tool -- that means, for one, that it's free to use. You can use it at no cost for private or non-profit projects, and also in government or commercial work too. It's also freely distributed: the code is available to everyone to read and even edit. If you are a programmer and want to add to or modify Leaflet's code, you are free to do that. A programmer could share his or her own version of Leaflet with the public, or they could create plugins that add to the existing Leaflet -- and share those plugins with the public.

So let's talk about putting these pieces together and making a web map!

The basemap

As said above, you can use the Mapbox Editor to make your own custom basemap. Mapbox tiles are based on OpenStreetMap data, and the Editor lets you adjust colors & symbology to fit your own map's needs. To use it, you'll need to make a (free) Mapbox.com account. All it takes is an email address! From there, go to the Editor and let your creative side go wild. Take note of your Map ID -- you'll need it later.

The map data

I grabbed the City of Austin's Points of Interest shapefile from the city's GIS data site. I then selected only the points that represented CoA libraries. After that, I converted the shapefile into a GeoJSON file, which is a common format used for making web maps.

In my talk I mentioned that you could use just about any GIS analysis tool to do the above work, but that I used something called ogr2ogr to do it all in one step. This is the command I used:

$ ogr2ogr -t_srs EPSG:4326 -f GeoJSON libraries.json facilities.shp -sql “SELECT * FROM facilities WHERE facility=’library’”

If you'd like to learn more about OGR tools, you might be interested in this tutorial series I posted here a while back.

The "map sandwich"

Once you have a basemap & some data, you're ready to put it all together. Leaflet is the "glue" we use to do that.

The code

If you're totally new to HTML & JavaScript - don't worry! Just follow along for now. You'll be surprised at how much sense you can make of the code after reading it through. You may also want to type this out for yourself: you can learn a lot doing that (instead of copy-pasting). When you're ready, there are lots of great learning resources online - here's one for HTML, and another for JavaScript. Once you have some basic foundational knowledge, the Leaflet website has a fantastic tutorials collection to check out next.

Here's the code I used to build the demo Leaflet map:

<!DOCTYPE html>
<html>
  <head>
        <title>City of Austin - Libraries</title>
        <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
        <script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
        <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
        <style>
        body {padding: 0; margin: 0 }
        html, body, #map { height: 100% }
        </style>
  </head>

  <body>
        <div id="map"></div>
        <script type ="text/javascript">
        var basemap = L.tileLayer(
                'http://{s}.tiles.mapbox.com/v3/sarasafavi.hjegnofh/{z}/{x}/{y}.png',
                                  {     maxZoom: 18     });

        $.getJSON('libraries.json', function(data) {
                var geojson = L.geoJson(data, {
                  onEachFeature: function (feature, layer) {
                          layer.bindPopup(feature.properties.NAME + '<br />'
                                                        + feature.properties.ADDRESS);
                  }
                });
        var map = L.map('map').setView([30.260, -97.770], 12);
        basemap.addTo(map);
        geojson.addTo(map);
        });

  </script>
 </body>
</html>

This is a basic HTML web page. Right now, all it contains is the web map (which is configured to take up the full browser window).

Let's look a couple key sections:

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

These lines are grabbing resources from elsewhere on the web to use in the web map. There's leaflet.css & leaflet.js - those are what Leaflet requires to work. There's also jquery - you can ignore that for now, but it's another open source JavaScript tool (not specifically related to web maps).

<div id="map"></div>

This line creates a div to hold the web map. I've named it "map", but technically you could give it any ID you like.

<script type ="text/javascript">
var basemap = L.tileLayer(
        'http://{s}.tiles.mapbox.com/v3/sarasafavi.hjegnofh/{z}/{x}/{y}.png',
                          {     maxZoom: 18     });

This is where the JavaScript code that will make the Leaflet map begins. Here, "basemap" is a new Leaflet tile layer. The tiles.mapbox.com URL references the pretty-basemap created earlier: make sure you change sarasafavi.hjegnofh to your Mapbox Map ID!

$.getJSON('libraries.json', function(data) {
                var geojson = L.geoJson(data, {
                  onEachFeature: function (feature, layer) {
                          layer.bindPopup(feature.properties.NAME + '<br />'
                                                        + feature.properties.ADDRESS);
                  }

This section is a little trickier: it's using the $.getJSON method from jQuery to grab the GeoJSON created earlier (that's libraries.json, which should be uploaded to your webserver). It then uses that data to create a new Leaflet GeoJSON layer. Finally, it defines popup windows for each feature in that layer, using the "name" & "address" values from our original dataset.

var map = L.map('map').setView([30.260, -97.770], 12);
        basemap.addTo(map);
        geojson.addTo(map);
        });
  </script>

This is creating a Leaflet map object and setting its view to somewhere near Austin's center. Add the basemap & GeoJSON layer to the map, and then end the JavaScript section.

The map

That's it! To see that map online, save that code somewhere (with a .html file extension) & upload it to your web server along with the libraries.json GeoJSON file. To see what that will look like, click here to view it now.

By @Sara Safavi