Basics of making maps with leaflet.js & browserify

Leaflet.js is an awesome, easy to learn mapping library. Here we’ll go through some introductory examples so you can get started using it in your projects.

Hey, if leaflet is a mapping library for browsers, what’s it doing on npm?

Client-side code can be distributed through npm, and combined with a tool like browserify, which bundles node modules for the browser, it works pretty great.

Make sure you have node installed. I recommend using a tool called nvm for installing node.js if you're using mac or linux.

nvm:

github.com/creationix/nvm.

If you're using Windows, install node.js using the .msi package on the nodejs.org downloads page:

nodejs.org/downloads.

Installation and setting up

First, create and navigate to a new project directory and create these files:

mkdir leaflet-example
cd leaflet example
touch index.html app.js style.css

Now run npm init to create a package.json file.

You should get something like this after you answer the questions:

{
  "name": "leaflet-basics",
  "version": "0.0.0",
  "description": "introduction to using leaflet with browserify",
  "main": "app.js",
  "scripts": {
    "start": "beefy app.js:bundle.js --live",
    "bundle": "browserify app.js -o bundle.js"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
  },
  "devDependencies": {
  }
}

Now install leaflet using npm

We'll use the --save argument so that leaflet.js is saved as a dependency in package.json

npm install --save leaflet

html and css

Create an html file that looks like this:

<!doctype html>
<html>
<head>
  <title>leaflet example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="node_modules/leaflet/dist/leaflet.css">
  <!--[if lte IE 8]>
    <link rel="stylesheet" href="node_modules/leaflet/dist/leaflet.ie.css" />
  <![endif]-->
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="map"></div>
  <script src="bundle.js"></script>
</body>
</html>

Note that for the stylesheets we’re providing the path directly to the leaflet package in the node_modules folder:

node_modules/leaflet/dist/leaflet.css

Our script tag points to bundle.js, which will be generated by a tool called beefy, which creates a development server with live reloading of browserify bundles.

Make sure the #map div has a height, otherwise the map won’t show up.

Add this to your the styles.css file:

#map {
  height: 300px;
}

require leaflet

Now, in the app.js file, require the leaflet module like this:

var L = require('leaflet');

You could probably use any variable name here, but L is a common variable name for leaflet. You’ll see it in the leaflet docs and tutorials.

fix image path

Because we’re using browserify, we need to tell leaflet the specific location of the images folder that it needs to render the page:

L.Icon.Default.imagePath = 'node_modules/leaflet/dist/images/';

Now we can create a map!

You can use the L.map() method to create the map:

var map = L.map('map');
map.setView([47.63, -122.32], 11);

The map.setView() method centers the map at a latitude/longitude, then sets the zoom level. In the above example the lat/long centers the map on Seattle, WA, and the zoom level is at 11.

Finally, we need to tell the map to use a specific tileset:

var attribution = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>';
 
var tiles = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png';
 
L.tileLayer(tiles, {
  maxZoom: 18,
  attribution: attribution
}).addTo(map);

It’s important to properly attribute tile image and data sources, so we’re setting the attribution variable to a string crediting OpenStreetMap and CloudMade.

Next the tiles variable is set to a url for a popular cloudmade tileset. Note that we’re using the api key that Leaflet uses in tutorials. For production code you should create an account on cloudmade.com, and create an api key for your app.

Then you can replace the !!!APIKEY!!! portion of the url seen below with your api key:

var tiles = 'http://{s}.tile.cloudmade.com/!!!APIKEY!!!/997/256/{z}/{x}/{y}.png';

Currently, your app.js file should look like this:

// require leaflet.js
var L = require('leaflet');
 
// specify the path to the leaflet images folder
L.Icon.Default.imagePath = 'node_modules/leaflet/dist/images/';
 
// initialize the map
var map = L.map('map', {
  scrollWheelZoom: false
});
 
// set the position and zoom level of the map
map.setView([47.63, -122.32], 11);
 
// set an attribution string
var attribution = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>';
 
// set the tiles the map will use
var tiles = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png';
 
// create a tileLayer with the tiles, attribution
var layer = L.tileLayer(tiles, {
  maxZoom: 18,
  attribution: attribution
});
 
// add the tile layer to the map
layer.addTo(map);

Serving the development site using browserify & beefy

Now that we've got our basic components together, let's use browserify and beefy so you can serve the site on your computer.

First, install beefy and browserify. Here we'll use the --save-dev argument so that these modules get saved in our package.json file as development dependencies.

npm install --save-dev beefy browserify

Now that those modules are installed, we'll use the beefy command to run a development version of the site:

beefy app.js:bundle.js --live

This command takes our node-style code in app.js, and bundles it using browserify to serve the bundle.js file. The --live argument enables live reloading of the page, so every time you save a file, the browser will reload.

We can make our lives simpler and not have to remember/type that command all the time by using npm scripts.

In your package.json file, and change the scripts property to look like this:

"scripts": {
  "start": "beefy app.js:bundle.js --live",
},

Now, we can run a much simpler command to run the site:

npm start

Run that and you'll be able to go to http://localhost:9966 to see your site.

Note that running beefy doesn't create a bundle.js file in your file system, it just serves one through the development server.

To create a bundle.js file that you can use to deploy on GitHub Pages or wherever you host your site, you'll use the browserify command.

This will generate a bundle.js file:

browserify app.js -o bundle.js

We can use npm scripts again to simplify this:

"scripts": {
  "start": "beefy app.js:bundle.js --live",
  "bundle": "browserify app.js -o bundle.js"
},

Now, the start command is one of the few that npm directly supports. We can create commands with arbitrary names like bundle, but to use it, we prepend it with the run command, so it'll look like this:

npm run bundle

Run the above command and that will create the bundle.js file you can use when deploying your site.

basic elements of a leaflet map

There are a few basic elements that you’ll use on regular basis for drawing on a map. Here’s a look at how to make each one of those:

UI Layers

popups

To get started learning popups, let’s make the map show a popup with the latitude and longitude of place we click on the map.

To create a popup, use the L.popup() method:

var popup = L.popup();

Next we need to listen for the click event on the map:

map.on('click', onClick);

We’ve passed a function named onClick to the event listener, so let’s create that function:

function onClick(e){
    popup
    .setLatLng(e.latlng)
    .setContent("You clicked the map at " + e.latlng.toString())
    .openOn(map);
}

markers

To create a marker, use the L.marker() method:

var marker = L.marker([47.63, -122.32]);
marker.addTo(map);

The above code will add a marker to the center of your map, as we're using the some lat/long for this marker as the map view.

Let's add a popup to that marker.

First, set some html content to a variable:

var markerHtml = 'this is a marker. pretty great, right?';

Next, bind a popup to the marker:

marker.bindPopup(markerHtml);

Now when you click on the marker, the popup will show up the the html you specified.

To make the popup open up by default, try this:

marker.bindPopup(popupContent).openPopup();

Now when you look at your map again, you'll see that the popup is open by default.

Vector layors

Vectory layers are the things you can draw on top of the map. Some of the basic types: lines, rectangles, circles, and polygons. In this section we'll make one of each of those vector layer types.

lines

We'll use the L.polyline method for drawing lines on the map. it takes an array of lat/long coordinates, and an options object. This method extends the base L.Path method, so you can also use any path options.

Here's an example:

var polylinePath = [
  [47.607204675859045, -122.3298454284668],
  [47.60182268729636, -122.32521057128906],
  [47.60095457276622, -122.32349395751952],
  [47.5998260023411, -122.32237815856934],
  [47.59842248977284, -122.32124090194701],
  [47.59655590441905, -122.32023239135741],
  [47.59175167310035, -122.32126235961914],
  [47.588278460128734, -122.32057571411133],
  [47.58329978624572, -122.31997489929199],
  [47.579478622338286, -122.3192024230957],
  [47.57756793579513, -122.3196315765381]
];

var polyline = L.polyline(polylinePath);
polyline.addTo(map);

This is a line along part of the I-5 highway in the Seattle area. Try it out in your map. Try changing the path to see what lines you can make. Remember that we made that popup that shows the lat/long when you click on the map. Use that to come up with coordinates that you want to place in your lat/lng array.

rectangle

Creating a rectangle is very similar to creating a polyline, but takes two coordinates as two corners as the rectangle.

Here's an example that loosely outlines Lake Union in Seattle:

var rectBounds = [[47.64614, -122.34555], [47.6274, -122.32839]];

var rectangle = L.rectangle(rectBounds);
rectangle.addTo(map);

circle

When creating a circle, we use the L.circle method and give one lat/lng coordinate as the center point, followed by the radius.

Here's an example with a circle centered on the Seattle neighborhood Fremont (also known as the center of the universe):

var circle = L.circle([47.65136, -122.35087], 300)
circle.addTo(map);

polygon

A polygon can be any arbitrary shape, good for outlining buildings, parks, etc. To create a polygon, we use L.polygon.

Here’s an example that really roughly outlines the downtown Seattle area:

L.polygon([
  [47.61311, -122.34967],
  [47.61594, -122.33156],
  [47.60466, -122.32169],
  [47.60211, -122.33551]
]).addTo(map);

What’s next

This gets you started with leaflet.js. You’ve learned about getting a map to show up on a page and drawing basic shapes. Just by composing shapes and popup markers in this way you can make a useful map very easily.

Seth Vincent

Seth makes weird arcades, writes JavaScript, and builds civic technology.
sethvincent.com
twitter.com/sethdvincent
github.com/sethvincent