Saturday, 25 January 2014

Making a simple map with leaflet.js


The following post is a portion of the Leaflet Tips and Tricks book which is free to download. To use this post in context, consider it with the others in this blog or just download the the book as a pdf / epub or mobi .
----------------------------------------------------------

Start With a Simple Map

We will walk through the building of a simple web page using an HTML file. The page will host a Leaflet map so that we can understand all the different portions of the file and the processes that needs to be gone through to make it happen.
This wont be an exact template for building on, since there are some liberties that are taken, but it will do the job and provides a base for explanation of the process and it will demonstrate how easy it can be.
The following is the full code listing of the file simple-map.html that we will be examining;
<!DOCTYPE html>
<html>
<head>
    <title>Simple Leaflet Map</title>
    <meta charset="utf-8" />
    <link 
        rel="stylesheet" 
        href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
    />
</head>
<body>
    <div id="map" style="width: 600px; height: 400px"></div>

    <script
        src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js">
    </script>

    <script>
        var map = L.map('map').setView([-41.2858, 174.78682], 14);
        mapLink = 
            '<a href="http://openstreetmap.org">OpenStreetMap</a>';
        L.tileLayer(
            'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: 'Map data &copy; ' + mapLink,
            maxZoom: 18,
            }).addTo(map);
    </script>
</body>
</html>
The output that it will produce on a web page will look like this;

You can access an electronic version from bl.ocks.orgGitHub there is a copy in the appendices and there is a copy of all the files that appear in the book that can be downloaded (in a zip file) when you download the book from Leanpub.
You can pan the map by pressing an holding the left mouse button and waving it about and you can zoom in and out of the map by either clicking on the + or - buttons or using a scroll wheel.
As you can tell from the code listing, there’s not much there, so what you can take from that is that there is a significant amount of cleverness going on inside leaflet.js.
Once we’ve finished explaining the different parts of the code, we’ll start looking at what we need to add in and adjust so that we can incorporate other useful functions.
The two parts to the code that we in our example to consider are;
  • HTML
  • JavaScript
Technically we could also consider some CSS, but the way that this example loads our styles is configured for simplicity, not flexibility as we will check out soon.

HTML

Here’s the HTML portions of the code;
<!DOCTYPE html>
<html>
<head>
    <title>Simple Leaflet Map</title>
    <meta charset="utf-8" />
    <link 
        rel="stylesheet" 
        href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
    />
</head>
<body>
    <div id="map" style="width: 600px; height: 400px"></div>

    <script
        src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js">
    </script>

    <script>

        The D3 JavaScript code is here

    </script>
</body>
</html>
Compare it with the full file. It obviously comprises most of the code for the web page which should tell you two things.
  1. The JavaScript portion that draws the map is really small (and therefore it should hopefully be pretty easy to understand (Spoiler alert: It is)).
  2. The heavy lifting done by leaflet.js must be pretty clever.
There are plenty of good options for adding additional HTML stuff into this very basic part for the file, but for what we’re going to be doing, we really don’t need to make things too difficult.
HTML works its magic by enclosing instructions for the browser in specific ‘tags’ A tag will begin with a descriptive word inside the greater-than and less-than signs and end with the same thing except the closing tag includes a backslash. There are also tags that allow including the contents inside a single tag that is closed off with a backslash. This appears to be connected with XHTML and sometimes with browser variants. To be perfectly honest I have trouble keeping up with it all.
For example, the title of our web page is ‘Simple Leaflet Map’. This is enclosed by an opening title tag (<title>) and a closing title tag (</title>). So that the whole thing looks like this; <title>Simple Leaflet Map</title>.
Each tag has a function and the browser will know how to execute the contents of a tag by virtue of standards for web browsers that builders of browsers implement. Tags can also be nested so hierarchies can be established to create complex instructions.
For example contained within our <head> tags;
<head>
    <title>Simple Leaflet Map</title>
    <meta charset="utf-8" />
    <link 
        rel="stylesheet" 
        href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
    />
</head>  
We can see the <title>, a <meta> tag and a <link> tag.
The title tag simply provides identification for the page. The <meta> tag defines the character set that is used for the page. But the link tag is a little different.
In this case we need to load a set of styles for Leaflet to use. We could have loaded these from a local file (stored in the css directory for instance), but in order to make the sample file a bit more transportable (we don’t need to ship it with a separate css file) the file reaches out with a link and pulls in the appropriate css file (leaflet.css) from an official location (http://cdn.leafletjs.com/leaflet-0.7/).
Inside the <body> tags we have two interesting sections.
The first is…
    <div id="map" style="width: 600px; height: 400px"></div>
<div> tag defines a division or a section in an HTML document. As well as creating a section we use an ID selector (id="map") as a way of naming the division as an anchor point on an HTML page. ID selectors can be defined as “a unique identifier to an element”. Which means that we can name a position on our web page and then we can assign our map to that position. Lastly for our division, we specify the size with a style declaration of width: 600px; height: 400px.
The second is…
    <script
        src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js">
    </script>
This tells the browser that we are loading a script (hence the <script> tags) and in this case, the script isleaflet.js which we get from http://cdn.leafletjs.com/leaflet-0.7/. This is using the same idea as we used for the css file. We are loading the leaflet.js script from the original authorised location when the file is loaded. We could have loaded this from a local file (stored in the js directory for instance), but again, in order to make the sample file a bit more transportable (we don’t need to ship it with a separate js file) we load it from an external source.

JavaScript

The JavaScript portion of our code looks like this;
    var map = L.map('map').setView([-41.2858, 174.78682], 14);
    mapLink = 
        '<a href="http://openstreetmap.org">OpenStreetMap</a>';
    L.tileLayer(
        'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data &copy; ' + mapLink,
        maxZoom: 18,
        }).addTo(map);
Firstly I have to apologise since it should look slightly simpler, but in order to make the code appear ideal for the book I have made it slightly less simple (but only slightly). But the main thing that we can take away from this piece of code is that there’s not very much there. The process of presenting a map on a web page has been rendered to a very few lines of code.
The heart of the process in the code above consists of two actions;
  1. Declare the starting parameters for the map.
  2. Declare the source of the map tiles.

Declaring the starting parameters for the map

The L.map statement is the key function to create a map on a page and manipulate it.
    var map = L.map('map').setView([-41.2858, 174.78682], 14);
It takes the form;
L.map( <HTMLElement|String> *id*, <Map options> *options*? )
Where the map object is instantiated given an appropriate div element or its id and (optional) map state options.
In our example it is declared as a variable using var map =. The id is set as map (recall that we declared a div with the id map in our HTML section).
The .setView method is used specifically to modify our map state. In this case setView sets the geographical centre of the map ([-41.2858, 174.78682] is the latitude and longitude of the centre point) and the zoom level (14).
If this all seems a bit rushed in terms of an explanation, never fear as we will go over as many mysteries of maps as possible in other sections of the book.

Declaring the source for the map tiles

The L.tileLayer function is used to load and display tile layers on the map.
    L.tileLayer(
        'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data &copy; ' + mapLink,
        maxZoom: 18,
        }).addTo(map);
It takes the form;
L.tileLayer( <String> *urlTemplate*, <TileLayer options> *options*? )
The urlTemplate is a string in the form http://{s}.mapdomain.org/{z}/{x}/{y}.png, where the {s} will allow one of the subdomains of the main domain to be used. These are typically used sequentially to make loading the map faster by allowing multiple parallel requests. The {z} declares the zoom level and the {x} and {y} define the tile coordinates. We will look closely at how these urls are formed in a future section of the book since they are an interesting feature in themselves and it is useful to understand their working in relation to the map being displayed.
The TileLayer options provides scope for a range of different options when loading or displaying the tiles. We will go over all of them in a later section.
In our example we are retrieving our tiles from openstreetmap.org and setting options for attribution andmaxZoom.
attribution is the placing of appropriate reference to the source of the tiles. The idea is to ensure that credit (and copyright acknowledgement) is provided to the tile provider as is reasonable. In the example used here we place the words ‘Map Data’ and then a copyright symbol (which is produced by the text &copy) followed by the variable mapLink which is declared slightly earlier in the JavaScript code and is set to<a href="http://openstreetmap.org">OpenStreetMap</a> which provides the text OpenStreetMap and a link to openstreetmap.org. The end result looks like this;

maxZoom sets the maximum zoom level of the map.
The .addTo method adds the tiles to the map.

And there’s your map!

Too easy right?
Now, there is a strong possibility that the information I have laid out here is at best borderline useful and at worst laden with evil practices and gross inaccuracies. But look on the bright side. Irrespective of the nastiness of the way that any of it was accomplished or the inelegance of the code, if the map drawn on the screen is effective, you can walk away with a smile. :-)
This section concludes a very basic description of one way of presenting a map on a web page. We will look as adding value to it in subsequent chapters.
I’ve said it before and I’ll say it again. This is not strictly a how-to for learning how to implement leaflet.js. This is how I have managed to muddle through in a bumbling way to try and put maps on a screen. If some small part of it helps you. All good. Those with a smattering of knowledge of any of the topics I have butchered above (or below) are fully justified in feeling a large degree of righteous indignation. To those I say, please feel free to amend where practical and possible, but please bear in mind this was written from the point of view of someone with little to no experience in the topic and therefore try to keep any instructions at a level where a new entrant can step in.


The description above (and heaps of other stuff) is in the Leaflet Tips and Tricks book that can be downloaded for free (or donate if you really want to :-)).

No comments:

Post a Comment