left-icon

Leaflet.js Succinctly®
by Mark Lewin

Previous
Chapter

of
A
A
A

CHAPTER 6

Geocoding

Geocoding


Often you want your users to be able to enter a location such as an address, landmark, or national park, and have your map instantly zoom to the correct location. GIS people have a term for that: geocoding. Leaflet.js, in case you haven’t already guessed, has a plugin for it. In fact, it has several. But the one I like, and which we’re going to look at in this chapter, is L.GeoSearch.

The accuracy of any geocoding operation is dependent entirely on the quality of the data available, and one of the reasons I really like L.GeoSearch is that it gives us the ability to geocode against the data of several different providers: Google, Esri, Bing, Nokia, and OpenStreetmap. The other reason is that, regardless of which provider you decide to use, it is really easy to implement, and even provides its own perfectly adequate user interface control. Let’s go ahead and use it.

First, visit the L.GeoSearch page on GitHub at: https://github.com/smeijer/L.GeoSearch and download the zip file:

The L.GeoSearch page on GitHub

Figure 51: The L.GeoSearch page on GitHub

Like most Leaflet.js plugins, L.GeoSearch consists of some JavaScript files and some CSS to style the control, so you can ignore most of the contents of the zip file. If you want to follow along with this example, just copy the .js files from the src\js folder in the zip file to a directory called js within the same directory that you’re going to write your code in. In my environment, I’m writing my code in Ch06_geocoding, which is a subdirectory of leafletsync on my local web server:

Placement of the L.GeoSearch JavaScript files

Figure 52: Placement of the L.GeoSearch JavaScript files

Then copy the l.geosearch.css file into a directory called css within the same directory that you are going to write your code:

Placement of the L.GeoSeach CSS file

Figure 53: Placement of the L.GeoSeach CSS file

We now need to create our HTML page, being sure to reference the L.GeoSearch files we added previously. In this example, I’m going to use OpenStreetmap as my provider, so I need a <script> tag reference to both the l.control.js and l.geosearch.provider.openstreetmap.js files.

If I wanted to swap providers at any stage, or even allow my users to choose the provider at runtime, then I’d need to reference the relevant l.geosearch.provider.[name].js file(s).

I also need to reference the l.geosearch.css file in a <link> ref, which will be used to style the control.

After creating a map, setting its extent to the U.S., and adding an OpenStreetmap basemap layer, this is our starting point:

Code Listing 48: Starting point for the Geocoding application

<!DOCTYPE html>

<html>

<head>

<title>My Leaflet.js Map</title>

<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css" />

<script src="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script>

<script src='js/leaflet-omnivore.min.js'></script>

</script>

<style>

    html,

    body,

    #map {

        height: 100%;

    }

</style>

<script type="text/javascript">

    function init() {

        var map = L.map('map').setView([0,0], 2);

        // OSM Mapnik

        var osmLink = "<a href='http://www.openstreetmap.org'>Open StreetMap</a>";

        L.tileLayer(

            'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

                attribution: '&copy; ' + osmLink,

                maxZoom: 18

            }).addTo(map);

        var runLayer = omnivore.kml('kml/2.5_month_age.kml')

            .on('ready', function() {

                map.fitBounds(runLayer.getBounds());

                runLayer.eachLayer(function(layer) {

                    layer.bindPopup(layer.feature.properties.name);

                });

            }).addTo(map);

    }

</script>

</head>

<body onload="init()">

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

</body>

</html>

Note: The choice of basemap layer is irrelevant. Just because you are using OpenStreetmap for your geocoding operations, you are not restricted to using OpenStreetmap tiles in your map.

Now we just need to create a new instance of the class for our chosen provider:

Code Listing 49: Creating a new instance of the appropriate provider's L.GeoSearch class

...

    new L.Control.GeoSearch({

        provider: new L.GeoSearch.Provider.OpenStreetMap()

    }).addTo(map);

...

And that’s it! Now, when we run the application, we get a nice text entry field at the top of the page. We can enter the name of a place, or part of an address and, depending on the quality of the provider’s data, get a more or less useful result.

Let’s try searching for Google’s headquarters in Mountain View, California:

Searching for Google HQ

Figure 54: Searching for Google HQ

There we are, right in the middle of the Googleplex. Note how L.GeoSearch instantly positions the map to the location of the search results, zooms in, and displays a marker based on the coordinates it has stored for the address.

Let’s see if it works on my address (no hate mail, please):

Searching for my home address

Figure 55: Searching for my home address

That’s pretty poor, actually. Google’s geocoding result puts me about 200 feet away from where I actually live. Let’s swap providers and give Esri a chance to beat Google. I just need to change the file I’m referencing in my <script> tag and the name of the class I’m using in the provider property of the L.GeoSearch control:

Code Listing 50: Using Esri as a provider

<!DOCTYPE html>

<html>

<head>

  <title>My Leaflet.js Map</title>

    <link rel="stylesheet"

      href="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css" />

    <link rel="stylesheet" href="css/l.geosearch.css" />

    <script src="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script>

    <script src="js/l.control.geosearch.js"></script>

    <script src="js/l.geosearch.provider.esri.js"></script>

    <style>

      html, body, #map {

        height: 100%;

      }

    </style>

    <script type="text/javascript">

        function init() {

            var osmLink = "<a href='http://www.openstreetmap.org'>Open StreetMap</a>"

            var map = L.map('map').setView([34.525, -97.778],5);

            L.tileLayer(

                'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

                attribution: 'Map data &copy; ' + osmLink,

                maxZoom: 18,

            }).addTo(map);

            new L.Control.GeoSearch({

                provider: new L.GeoSearch.Provider.Esri()

            }).addTo(map);

        }            

    </script>

</head>

<body onload=init()>

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

</body>

</html>

This is what Esri came back with:

Esri's geocoding result on my address

Figure 56: Esri's geocoding result on my address

Much better! (Even though I don’t live in the middle of the road.) The moral of this story is that all geosearch providers are not created equal, especially if you are searching for addresses outside of the USA.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.