By Lyzi Diamond

March 26, 2019

Make a Web Map with Leaflet

Leaflet is a JavaScript library for making interactive web maps. This library allows you to create a map container, add a base map, and add interactive features on top of the map — plus panning and zooming. The base map is made of tiles, or small images that each represent a specific geographic location. The interactive features, or “data layer,” consists of geospatial vector data — points, lines, and polygons with associated geographic information. Collectively, this kind of map is known as a slippy map.

For the Leaflet Starter App, we created a map showing neighborhood boundaries in Portland, Oregon. In Portland there are neighborhood coalitions as well as neighborhood associations, so the data is styled based on which neighborhood coalition the association belongs to. It also has interactive elements — neighborhood associations are highlighted when hovering over them, and popups show the name of the neighborhood association when clicked.

In the next section, we describe how the code in this app works. Feeling comfortable with the app? Skip down to “” and get started!

How it works #

The code powering this app is in index.html, style.css, script.js, and in the assets directory.

The data for this map comes from the City of Portland as a GeoJSON file. GeoJSON is a specific flavor of JSON that is used to describe geographic vector features (points, lines, and polygons). We downloaded this file and then uploaded it to the assets directory in our Glitch app so we can request the data with JavaScript when creating the map.

index.html contains the main structure of the page as well as any additional files the app needs to run effectively. In the section we add links to the Leaflet JavaScript and CSS files and in the we add an empty

with id="mapid”.

In order for the map to render, the

element housing it must have a height. We can make the height responsive by setting html and body to height:100% and then giving #mapid a percentage value for height.

script.js is where we actually make the map, add layers to it, and add event handlers to make the map interactive. First things first — we have to make a map!

The file starts by creating a L.map object, which takes two parameters: the id of the

where the map should live on the page, and an optional object to specify more options. In this case, we tell the map to put itself in the ”mapid”
and set the map’s initial center point and zoom level to center on Portland.

Now we start adding things to the map, with the base map tiles up first. For this map we are using the Stamen Toner tileset (lite version). We create an L.tileLayer, point it to the URL of the tile server, and add it to the map.

At this point, we have a map that pans and zooms around and a base map to look at while you pan around. Great! But that’s not the point of our map — the point of our map is to show neighborhood associations in Portland. But before we add the data, we have to do a little bit of setup work by defining some event handlers.

Event handlers are functions that respond to events on the page. These are defined before we load in the data so they can be attached to the data layer and triggered on specific events. We create four event handler functions: highlightFeature, resetHighlight, zoomToFeature, and onEachFeature, which attaches the other three functions to specific mouse events as they relate to the data on the map.

Because the neighborhood association data we’re using is in a different file, it must be retrieved asynchronously. This ensures that all of the data has been loaded before trying to use it (in this case, add it to the map). For the most part, you’re going to want to leave this section alone, except to change the URL so it matches your data. The important thing to know here is that once the data is loaded, the doThingsWithData function is called.

(If you're interested to know more about how we're loading the data, you can read more about using Fetch)

doThingsWithData is where we (yup you guessed it) add the data to the map. In this case, we want to style the neighborhood associations based on their neighborhood coalition (a coalition consists of multiple neighborhood associations). To do that, we create a variable colorObj and assign to it the returned value from assignColors — an object assigning each unique coalition to a color.

The second part of doThingsWithData adds the data to the map with L.geoJSON by passing the data as the first parameter. The second parameter is an optional object containing additional specifications — we use it here to set the style for each feature and add the event handlers. We then call two methods on the L.geoJSON layer — bindPopup, which adds a popup to each feature, and addTo(map) which adds the layer to the map.

  • assets is where we add the GeoJSON data file
  • index.html contains an empty
    with id=“mapid”
  • style.css gives our ”mapid”
    a height
  • script.js creates the map, adds the base map layer and data layer, and adds interactive elements/event handlers (popups, highlighting, zooming)

The Challenge #

For this challenge, you have several options. Each challenge concerns a different part of the map — if you’re feeling up to it, try all of them!

  • Make the popups look pretty — add some styling, change the names to title-case, etc.
  • Some Portland neighborhoods have overlapping boundaries — the dataset used in this map has these areas as separate polygons. Use styling to make it clear that these are overlap areas.
  • Add a legend to this map.
  • Change out the GeoJSON file for a file of your choosing, ideally in a different location. Think about what might be different between the two datasets. (Data.gov is a great place to find GeoJSON data!)
  • Leaflet has some special things you can do when adding markers to a map. Add some point data and do some cool marker stuff. After you’ve made your super radical map, submit it using the form below. We are so looking forward to checking out your amazing work! If you have any questions or need help, reach out on Twitter @glitch or via our support forums.