Leaflet part 1 - NieneB/webmapping_for_developers GitHub Wiki
Leaflet is an open-source JavaScript library for interactive web maps. It's lightweight, simple, and flexible, and is probably one of the most most popular open-source mapping library at the moment. Leaflet is developed by Vladimir Agafonkin (currently of MapBox) and other contributors.
Leaflet creates "Slippy" maps with raster tiled base layers, user interaction like panning and zooming, and feature layers that you supply. It handles various basic tasks like converting data to map layers and mouse interactions, and it's easy to extend with plug-ins. It will also work well across most types of devices.
Web maps are made up of many small, square images called tiles. These tiles are typically 256x256 pixels and are placed side-by-side in order to create the illusion of a very large seamless image. A big advantage: all these little tiles load way faster than one big map! This kind of map is called a "Slippy" map.
Each zoom level has its own set of tiles. Zoom level 0 has 1 tile for the world. With each additional zoom level, the number of tiles increases exponentially. So zoom level 1 has 4 tiles for the world. Zoom level 2 has 16 tiles for the world ect. Learn more about the google tiling scheme.
As you can see, map tiles are static raster images on the web. These tiles need to live somewhere on the web page. They need to know when to load and they need to react when you click or drag. Leaflet is a JavaScript library that allows us to do just that.
During the workshop we will work with a simple HTML page example. The examples can also be found in the git repository. Feel free to set up a folder and structure for yourself or work in any framework you'd like.
For this workshop, we assume you already know HTML,CSS and some JavaScript. If not see the Webmapping for Beginners workshop. This is almost the same workshop but includes more explanation about the basic concepts of HTML, CSS and JavaScript.
<!DOCTYPE html>
<html>
<head>
<title> My title </title>
</head>
<body>
<H1>Example</H1>
<script></script>
</body>
</html>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
leaflet.css Link
in the <head>
of your html file.
leaflet.js script
library in the <body>
.
We will need a <div>
were our map will be placed.
<div>
with an id="map"
in the <body>
<div id="map"></div>
The map needs a height and width in order to be seen. Add a bit of CSS to the HTML document. The following is sufficient:
#map {
height: 500px;
width:100%;
}
Initialize a map by creating a L.map
instance with JavaScript.
<script>
//initialize the map
let map = L.map('map').setView([51.9741, 5.6688], 15);
</script>
ℹ️ let map = L.map('map')
initializes the map
variable and links it to our <div id="map"></div>
. This will link the map content to the <div>
container.
ℹ️ setView()
centres the map at ([latitude, longitude], zoom level)
. The projection is Google Mercator.
Apart from the setView
we did not pass any options when creating the map instance. So by default, all mouse and touch interactions on the map are enabled and it has zoom and attribution controls.
The map instance is customizable with Options
. We will come back to this later.
🔗 Read the map instance documentation here.
Let's first add our Baselayer, because we do not have a map yet only the framework for the map.
A Base layer can also be called a basemap, reference map, TileLayer or tile provider. It consists of the multiple PNG images, so-called 'tiles'. It is possible to create tiles yourselves and host them yourselves. But this requires some GIS skills and map render/serving skills. Luckily there are also a lot of tile providers out there, offering you free or on subscription tile services.
We will add a base layer with the L.TileLayer
instance and a Open Street Map provider.
🔗 Read the TileLayer documentation here.
<script>
//initialize the map
let map = L.map('map').setView([51.9741, 5.6688], 15);
//Create base layer
let backgroundMap = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
});
// add layer to map instance
backgroundMap.addTo(map);
</script>
ℹ️ We create a base-layer with L.tileLayer('http://...')
this grasps the static tiles from the internet and Leaflet knows how handle them to make and interactive map.
ℹ️ backgroundMap.addTo()
adds the tile layer to the map. Your map can contain multiple layers. You will see later on.
Now you have made our first basic web map!
Do you see your map? Great!
We can also define our map options before and pass it into the map instance on creation, like this:
let options = {
zoom: 12,
center: [52.38031476, 4.90273476],
maxZoom: 19,
minZoom: 6,
maxBounds: [[ 51.8716, 3.8133], [ 52.8271, 6.4494]]
}
let map = L.map('map', options );
🔗 Use the Leaflet documentation to see all the map options
ℹ️ Looking for a specific place to centre on? Find your coordinates here: mapcoordinates.net
ℹ️ The minZoom
and maxZoom
restrict the map from zooming in or out further then those zoom levels. If you want to know how far "zoomed" in you are, have a look at this description of scales and examples about zoom levels.
ℹ️ The maxBounds
are the coordinates of a bounding box to which the user is restricted. Check the latlngbounds documentation. 🔗 Finding easy creation of bounding boxes at: https://boundingbox.klokantech.com/
A boundingbox is an important geo type to know. It represents a rectangular geographical area on a map. Defining a bounding box works different in different frameworks. But mostly takes in 2 coordinates for 2 corners, left top and right bottom to define a rectangle.
Using these kind of map options, limits the use of the map to a great extent! When using a paid subscription plan on a tile provider this can be very useful. But also the IX design can be improved with these settings. People are directed to what you want to show them on the map and cannot "get lost" or use the map for different purposes. So do not forget about what you want the user to see and use these map options! :)
There are many different tile providers! Just copy their example code, replacing your own code starting from L.tileLayer (... );
Have a look at this Leaflet provider preview application.
Leaflet.js contains only the most basic task for making a web map. That why it is so light-weight and fast. Ideal for small maps on mobile applications with limited internet access.
If you want to have more elaborate functionality in your map we will need to add plugins.
A useful (and small) plugin for example is Leaflet-hash plugin. This plugin shows the position of your web map in the url of your web page. It gives the z
: zoom level and the x
and y
coordinate. Now you can always return to the map where you last opened it, or share a specific location with someone else!
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-hash/0.2.1/leaflet-hash.js"></script>
hash
to our map. Put the code under the map variable:
// Hash in URL
let hash = new L.Hash(map);
That's it!
The inital
z/x/y
map position set in your code only works when initializing the map for the first time. Refreshing the browser with thez/x/y
hash in the url will re-open the map at this last location, not the initial location you set in your code!If you want to go back to your original location set in your code, remove the
z/x/y
hash from the url to refresh the map.
Every time something happens in Leaflet, e.g. user clicks on a marker or map zoom changes, the corresponding object sends an event which you can subscribe to with a function. It allows you to react to user interaction:
function onMapClick(e) {
alert("You clicked the map at " + e.latlng);
}
map.on('click', onMapClick);
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 above) has latlng property which is a location at which the click occurred.
Let’s improve our example by using a popup instead of an alert:
let popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
Read more about the L.popup()
instance at the documentation
Try clicking on the map and you will see the coordinates in a popup.
➡️ Continue to Leaflet part 2 to add points, markers, circles and polygons to our map.