Deploy your own slippy map

schermafdruk rejo.zenger.nl met openstreetmap.nl kaart

From time to time I do some long-distance walking and multiple days of trekking. Most of the time, I carry my GPS with me, allowing me to keep track of the route I have walked. Sometimes I want to share the route with other people. Printing this route on top of Openstreetmap map is nice. This article describes a way to do this.

Openstreetmap and your GPX file

This is a GPS track of 2009′s Rode Kruis Bloesemtocht.

Over at osm.org there is a description on how to add a GPX track on an OSM map and embed this map onto a webpage: OpenLayers Simple Example. Apart from the lenghty Javascript you need to add to a webpage, additional problems include the necessity to specify the centering coordinates and zoomlevel yourself each and every time.

With some customizations, embedding this map on this page doesn’t take more than a single <iframe> tag. You may include multiple <iframe> tags to include embed multiple maps with different GPX tracks each. How I do this?

How to do this?

This page includes a single <iframe> tag to include the file that actually takes care of loading all the required components. A GET variable is used to tell the which GPX file needs to be loaded and rendered. The line in the source of this webpage:

<iframe
	src="osm-gpx.php?gpx=2009-04-18.gpx"
	width="480"
	height="250"
	frameborder="0">
</iframe>

The file osm-gpx.php returns the actual <div> that contains the map, provided the GPX file that was requested has a valid syntax and is readable:

<?php
if (isset($_GET['gpx'])) {
        if (preg_match('/^[a-z0-9-.]+\.gpx$/i', $_GET['gpx'])) {
                $gpx = $_GET['gpx'];
        }
}

if (isset($gpx) && is_readable($gpx)) { ?>
        <html>
         <head>
          <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
          <script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
          <script src="https://rejo.zenger.nl/topo/osm-gpx.js"></script>
         </head>
         <body onload="init('<?php echo $gpx;?>');">
          <div style="width:100%; height:100%" id="map"></div>
         </body>
        </html>
<?php } else { ?>
        <html>
         <head>
          <link rel="stylesheet" media="screen" type="text/css" href="/css/site-regular.css">
         </head>
         <body>
          <p>No valid GPX file provided.</p>
         </body>
        </html>
<?php } ?>

The file loads three Javascript files. One of the files is from openstreetmap.org, one from openlayers.com and a local one. The contents of the local file:

var map;

function init(gpxfile) {
	map = new OpenLayers.Map ("map", {
		maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
		maxResolution: 156543.0399,
		numZoomLevels: 19,
		units: 'm',
		projection: new OpenLayers.Projection("EPSG:900913"),
		displayProjection: new OpenLayers.Projection("EPSG:4326")
	} );

	layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
	map.addLayer(layerMapnik);

	var lgpx = new OpenLayers.Layer.GML("GPS route", gpxfile, {
	    format: OpenLayers.Format.GPX,
	    style: {strokeColor: "red", strokeWidth: 5, strokeOpacity: 0.5},
	    projection: new OpenLayers.Projection("EPSG:4326")
	});
	map.addLayer(lgpx);

	if( ! map.getCenter() ){
		lgpx.events.register('loadend', map, function(){this.zoomToExtent(lgpx.getDataExtent())});
		map.setCenter(null, null);
	}
}

init();

Basically, that’s it. Just upload the GPX file to your webserver, point to it from the <iframe> and you are done. Or if you want to have it even more easier, just provide the track.

Use the source, Luke!

From time to time people are asking me on details of my implementation. Here is a tarball of the files I am using. I love to hear your experience.