Tutorial #40
Display KML in a Google Map Intermediate   2014-01-14

Introduction

In Tutorial #28: Shapefiles, GeoJSON and KML I covered three of the most popular ways to represent geographic features. One of them, KML (Keyhole Markup Language), was created during the development of the precursor to Google Earth and so it is not surprising that this format is well supported in Google Maps. KML differs from GeoJSON in that it can include style information along with the coordinates of the features.

This tutorial shows how to load a KML file into Google Maps, overlaying its features on Google's Base Map. The KML file includes a Polygon, which represents the Fremont neighborhood in Seattle, and a Marker, which marks the location of a local landmark.

Demo 1 screenshot for this tutorial

Clicking on the marker brings up a Popup WIndow that renders HTML that is contained in the KML file.

Image 1 for this tutorial


KML File format

KML files are written in XML. The complete format is described in Google's KML Reference, but I will give a quick introduction here.

Below is an edited portion of the file used in this demo. It contains one <Style> and two <Placemark> blocks.

You can omit the Style block and Google Maps will use default styles, but including it offers a lot of control over the final display. In this example there are style definitions for Lines and the fill style for Polygons

Colors in KML are NOT specified in hexadecimal RGB format. Instead they are represented as 8 hexadecimal characters, the pairs of which represent Alpha Transparency, Blue, Green and Red, in that order - the reverse of RGB.

Each value has a range from 00 to ff. The first example shown here is ff000000 which means fully opaque and black. The second example is 7FAAAAAA and this means 50% transparent and light gray.


The first Placemark defines a Point at the specified coordinates along with a name and description that are used to label it.

Coordinates in KML are not simply Latitude and Longitude. Each of them has a third number that represents the altitude of the point. In most cases this will be 0, which is interpreted as being on the ground at that point at whatever altitude that happens to be. In the majority of cases you can just set this to zero and not worry anbout it - but you do need to include it.

The Name and Description are used in Google Maps to provide more information when a user clicks on a place marker. The Description can be plain text but it is often nicer to include HTML. This example includes a link to an external site as well as an image.

If you do this then you should wrap the HTML in a CDATA block, which saves you from having to escape all the HTML Entities in your content. This wrapper consists of <![CDATA[ at the start and ]]> at the end.


The second Placemark defines a polygon which, here, represents the boundary of a city neighborhood. This consists of an array of coordinates where the First and Last are identical and thereby close the polygon path.

This is a simple example of a Polygon. See the KML Reference for all the details of what you can represent in these files.


<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>

  <Style id="polygon_style">
    <LineStyle>
      <color>ff000000</color>
      <width>1</width>
    </LineStyle>
    <PolyStyle>
      <color>7FAAAAAA</color>
      <fill>1</fill>
      <outline>1</outline>
    </PolyStyle>
  </Style>

  <Placemark>
    <name>Fremont Troll</name>
    <description>
        <![CDATA[
      <p>The <a href="http://en.wikipedia.org/wiki/Fremont_Troll">Fremont Troll</a> is a large concrete sculpture <br>
      of the mythical troll who lives under the bridge.</p>
      <p>The troll is holding a Volkswagen bug in his hand.</p>
      <img src="/assets/FremontTroll.jpg" height="100px" />
            ]]>
    </description>
    <Point>
      <coordinates>-122.3473413,47.651119,0</coordinates>
    </Point>
  </Placemark>

  <Placemark>
    <name>Fremont</name>
    <styleUrl>#polygon_style</styleUrl>
    <Polygon>
      <outerBoundaryIs>
        <LinearRing>
          <coordinates>
            -122.3550974911330,47.6621379460780,0.000000
            -122.3545755477560,47.6621309868331,0.000000
            [...]
            </coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>
  </Document>
</kml>

In most cases you will not write your own KML files. You will adapt existing files or create one using a tool designed for the job. Google Earth is the easiest way to get started with your own KML files.

Because the file format is complex it is easy to mess things up if you are hand editing a KML file. Always check your file before you try loading it as an overlay to Google Maps. Start up Google Earth and from the File menu, open your KML file. If it displays correctly here then it should work in Google Maps. Here is what the demo KML file looks like:

Image 2 for this tutorial


Understanding the Code

The code necessary to display a KML file is not complicated.

The HTML consists of a div with the id map_canvas, with associated CSS to place it in the center of the page and define its size.

The first script loads the Google Maps API Javascript with the Maps API Key that you have created for your site.

Your Google Maps API key is tied to a Specific Server - if you try and use it on localhost while you are developing code you will get an error alert. This can be very annoying. You need to keep pushing changes to a remote server in order to test your code.

In the second script we first define a Latitude and Longitude pair that represents the center of the map that we want to display.

The initialize function creates a mapOptions has with the center, zoom level and map type, and uses this to create a Map object that is linked to the map_canvas div.

Now we load the KML file. There are three important things to remember here.

1: The KML file must be hosted on a server - you are not able to load a file on your local filesystem.

2: You must refer to the KML file with the Full URL (e.g. http://web-apprentice-demo.craic.com/assets/maps/fremont.kml) - a relative URL like /assets/maps/fremont.kml will not work.

class='note'>3: KML files are cached, like images, so if you are changing your file during development then you need to avoid this. Adding a unique string as an argument to the URL is an easy way to deal with this.>

A simple way to create a unique string is to convert the current time to a string, as shown here.

A KmlLayer object is created with the URL as its argument and then linked to the map with setMap. There are other options that you can specify with the a KmlLayer. You would create an options hash and pass this as the argument to the function instead of the URL.

Finally, we call google.maps.event.addDomListener which calls initialize when the page loads and displays the map.

By default, Google Maps will center and zoom a map to focus on the loaded KML elements. This may not be what you want. If not then use a layerOptions object literal when creating the KmlLayer and include preserveViewport: true.

Debugging a KML file that fails to load can be frustrating as the Maps API does not seem to echo any errors to the JavaScript console. My advice is to start with a simple example and add new features/datasets one by one. Check that your KML files are valid by opening them in Google Earth directly.

KML layers are loaded asynchronously. With a single KML file this is not a problem but if you try to load multiple files then the order they are displayed may not be same between page loads. The solution to this is to check that the first file has finished loading before starting the second, etc.

This tutorial is just scratching the surface of what you can do with KML and Google Maps. See the Google documentation and examples to learn more.


More Information

Google has a number of resources on KML:

KML Documentation Introduction

KML Tutorial

KML Reference

KML Developers Guide

Google Maps Layers documentation

KML Support in Google Maps

Google Maps KML Tutorial

To find more KML files, that you might want to experiment with, run a Google search with filetype:kml as one of the search terms - for example : filetype:kml castle


Code for this Tutorial


Share this tutorial


Related Tutorials

15 : Display a Google Map using JavaScript   (Intermediate)

28 : Shapefiles, GeoJSON and KML   (Background)

41 : Display GeoJSON in a Google Map   (Intermediate)


Comment on this Tutorial


comments powered by Disqus