Click here to Skip to main content
12,251,027 members (42,313 online)
Click here to Skip to main content
Add your own
alternative version

Stats

23.4K views
1.6K downloads
42 bookmarked
Posted

Generate a Google Map

, 12 Nov 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
How to generate a simple map image, using Google's Map API

Introduction

This article shows how to create a map image in your browser, showing a number of location markers that are taken from a list of addresses, using a few HTML lines and client side JavaScript. It also demonstrates a simple trick to add labels to the marker pins on that map. The locations are specified as human readable addresses, which are then converted to GPS coordinates using Google's Geocoder. As a bonus, a progress bar shows while doing the location lookups.

Background

It took me a few hours to get all information and put it together to a working demo. So I figured it would be a good idea to publish this working example to safe you some time.

Using the code

The example map is generated by a single HTML file, which has the HTML code and Javascript combined. Let's go through the code block by block, from top to bottom of the file.

Google API declaration

The first part of the file contains the HTML header and Google API 'declarations' (please forgive me if I don't use the correct terminology):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Points of interest</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <script src="https://maps.googleapis.com/maps/api/js?v=3.11&sensor=false" 
                   type="text/javascript"></script>

List of locations to look up

A a next step, the list of locations is defined as an Array of simple strings. Comma's are used to separate the fields within a location string. The first field serves as the name, the rest is the address itself. Also note that the whole Java scripting is started when the document loading is ready():

<script type="text/javascript">
    $(document).ready(function() {
        // execute
        (function() {
            // Points of interest
            var locations = new Array();
            var i = 0;
            locations[i++] = "Rijksmuseum, Museumstraat 1, Amsterdam"
            locations[i++] = "Van Gogh Museum, Paulus Potterstraat 7, Amsterdam";
            locations[i++] = "Kroller-Muller Museum, Houtkampweg 6, Otterlo";
            locations[i++] = "Beeckestijn, Rijksweg 136, Velsen";
            var total_locations = i;
            i = 0;

The variable total_locations is introduced to calculate the progress (discussed later on).

Creating the map

Now comes the interesting part. A variable options is created with a number of elements:

  • zoom: sets the default zoom level of the map;
  • center: specifies the center of the map, using GPS coordinates (latitude, longitude);
  • mapTypeId: for this example we use terrain;
  • mapTypeControl: set to 'true' so that controls are added to the map (zoom, navigate).

Then a new instance of the map is created with the options specified. The 'map_canvas' identifier comes from the HTML part. It is the identifier of a <div> element to hold the map image.

console.log('About to look up ' + total_locations + ' locations');
// map options
var options = {
    zoom: 8,
    center: new google.maps.LatLng(52.2313, 4.83565), // Amstelhoek, center of the world
    mapTypeId: google.maps.MapTypeId.TERRAIN,
    mapTypeControl: true
};

// init map
console.log('Initialise map...');
var map = new google.maps.Map(document.getElementById('map_canvas'), options);

Looking up the locations, slowly...

When not using a Google API key, the number of Geolocation lookups per second is limited. If we perform too many queries, an error result code is returned by the Google Maps API server. So let's prevent that by limiting the number of location lookups to one per second. For this, the setInterval method is used:

// use the Google API to translate addresses to GPS coordinates
var geocoder = new google.maps.Geocoder();
if (geocoder) {
    console.log('Got a new instance of Google Geocoder object');
    // Call function 'createNextMarker' every second
    var myVar = window.setInterval(function(){createNextMarker()}, 1000);

When the 1000 millisecond interval expires, it calls createNextMarker in our JavaScript:

function createNextMarker() {
    if (i < locations.length) {
        var customer = locations[i];
        var parts = customer.split(",");
        var name = parts.splice(0,1);
        var address = parts.join(",");
        console.log('Looking up ' + name + ' at address ' + address);
        geocoder.geocode({ 'address': address }, makeCallback(name));
        i++;
        updateProgressBar(i / total_locations);
    } else {
        console.log('Ready looking up ' + i + ' addresses');
        window.clearInterval(myVar);
    }
}

Here, a little trick is performed. The geocoder.geocode method takes a callback as last argument. This will be called once the reply has been received from the server. That reply contains the GPS coordinates and address details, but not the original name from our list of locations. To have that name value available in the context of the callback, we use the trick as shown in the code fragment above. Note that makeCallback returns the function variable (geocodeCallBack) of the actual callback that will be called by geocoder.geocode. It will then parse the result (results[0]) and place the marker on the map.

function makeCallback(name) {
        var geocodeCallBack = function (results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                var longitude = results[0].geometry.location.lng();
                var latitude = results[0].geometry.location.lat();
                console.log('Received result: lat:' + latitude + ' long:' + longitude);
                var marker = new google.maps.Marker({
                    position: new google.maps.LatLng(latitude, longitude),
                    map: map,
                    title: name + ' : ' + results[0].formatted_address});
            } else {
                console.log('No results found: ' + status);
            }
        }
        return geocodeCallBack;
    }
} // endif geocoder

Progress bar

Just for fun and to show some animation while looking up the geolocations, a progress bar is shown:

function updateProgressBar(percentage_factor) {
            var map_canvas = document.getElementById('map_canvas');
            var node = document.getElementById('progress_bar');
            var w = map_canvas.style.width.match(/\d+/);
            w = w * percentage_factor;
            node.style.width = parseInt(w) + 'px';
            if (percentage_factor == 1) {
                // jscript style properties are different to the CSS style properties
                node.style.backgroundColor = 'green';
            }
        }
    // Closing bits of jscript...
    })();
});
</script>

HTML code

</head>
    <body>
    <div style="border: 1px solid black; width:1024px; height:3px;">
        <div id="progress_bar" style="height:3px; width:0px; background-color:red;"/>
    </div>
    <!-- if you change this id, then also update code of progress bar above -->
        <div id="map_canvas" style="width: 1024px; height:600px;"></div>
    </body>
</html>

Browser security

When first loading the HTML code, the security settings of your browser may prevent display of the map. Internet Explorer shows a pop-up bar at the bottom of the page. Firefox and Chrome show a shield icon in the address bar. Click it with the mouse and choose the option to disable security for this page.

Points of Interest

The thing that I have learned from the examples that are already published on the net, is the trick of passing a variable value to a callback. The rest of the code is actually pretty straight forward and already available on the net, but not combined into a working example as shown here.

History

  • 12 November 2013: Initial version.
  • 13 November 2013: Fixed small typo and added security note.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Fred van Lieshout
Technical Lead Sioux Automation Technology, Utrecht
Netherlands Netherlands
Fred is an experienced software engineer with in-depth knowledge of software design, coding and testing. He is interested in the analysis, requirements and design phases in particular, but still enjoys ‘getting his hands dirty’ with software programming.

LinkedIn: profile

You may also be interested in...

Comments and Discussions

 
GeneralCongrats Pin
Member 1163950424-Apr-15 4:55
memberMember 1163950424-Apr-15 4:55 
QuestionQuestions about info window and using inside another <div> Pin
Gary Henning25-Aug-14 13:51
memberGary Henning25-Aug-14 13:51 
AnswerRe: Questions about info window and using inside another <div> Pin
Fred van Lieshout25-Aug-14 20:32
memberFred van Lieshout25-Aug-14 20:32 
GeneralRe: Questions about info window and using inside another <div> Pin
Gary Henning11-Sep-14 7:20
memberGary Henning11-Sep-14 7:20 
GeneralRe: Questions about info window and using inside another <div> Pin
Fred van Lieshout11-Sep-14 19:46
memberFred van Lieshout11-Sep-14 19:46 
GeneralMy vote of 5 Pin
Gun Gun Febrianza13-Nov-13 5:20
member Gun Gun Febrianza13-Nov-13 5:20 
Questioni love this article :) Pin
Gun Gun Febrianza13-Nov-13 5:19
member Gun Gun Febrianza13-Nov-13 5:19 
AnswerRe: i love this article :) Pin
Fred van Lieshout13-Nov-13 19:45
memberFred van Lieshout13-Nov-13 19:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160426.1 | Last Updated 13 Nov 2013
Article Copyright 2013 by Fred van Lieshout
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid