User:MHohmann/OLPopupGPX

From OpenStreetMap Wiki
Jump to: navigation, search

I recently faced the task of presenting GPX data on a web-based slippy map, so that information included as comments / descriptions in the GPX files is shown in popup boxes. After some trial and error, I finally managed to create such a map using OpenLayers. Here are two examples; have a look at the source code for more information.

Here is a simple, commented example source:

<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<title>GPX Popup Example</title>
	<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
	<script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
	<script type="text/javascript">
		var map;

		function init()
		{
			// First of all, we need to create the map.
			map = new OpenLayers.Map ("map", {
				controls:[
					new OpenLayers.Control.Navigation(),
					new OpenLayers.Control.PanZoomBar(),
					new OpenLayers.Control.LayerSwitcher(),
					new OpenLayers.Control.Attribution()],
				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")
			} );

			// Add the base layers.
			map.addLayer(new OpenLayers.Layer.OSM.Mapnik("Mapnik"));
			map.addLayer(new OpenLayers.Layer.OSM.Osmarender("Osmarender"));

			// This will enable us to autozoom the map to the displayed data.
			var dataExtent;
			var setExtent = function()
			{
				if(dataExtent)
					dataExtent.extend(this.getDataExtent());
				else
					dataExtent = this.getDataExtent();
				map.zoomToExtent(dataExtent);
			};

			// Now add a layer for the GPX data. The file "Somefile.gpx" contains some GPX data - in this case, waypoints and routes.
			var lgpx = new OpenLayers.Layer.Vector("GPX Data", {
				protocol: new OpenLayers.Protocol.HTTP({
					url: "Somefile.gpx",
					format: new OpenLayers.Format.GPX({extractWaypoints: true, extractRoutes: true, extractAttributes: true})
				}),
				strategies: [new OpenLayers.Strategy.Fixed()],
				style: {fillColor: "darkred", strokeColor: "red", strokeWidth: 2, strokeOpacity: 0.5, pointRadius: 5},
				projection: new OpenLayers.Projection("EPSG:4326")
			});

			// This will perform the autozoom as soon as the GPX file is loaded.
			lgpx.events.register("loadend", lgpx, setExtent);
			map.addLayer(lgpx);

			// This function creates a popup window. In this case, the popup is a cloud containing the "name" and "desc" elements from the GPX file.
			function createPopup(feature) {
				var lonlat = feature.geometry.getBounds().getCenterLonLat().clone();
				lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
				feature.popup = new OpenLayers.Popup.FramedCloud("gpx",
					feature.geometry.getBounds().getCenterLonLat(),
					null,
					'<div><h1>' + feature.attributes.name + '</h1><p>' + feature.attributes.desc + '</p><p>' + lonlat.lat + '° N</p><p>' + lonlat.lon + '° E</p></div>',
					null,
					true,
					function() { selcontrol.unselectAll(); }
				);
				map.addPopup(feature.popup);
			}

			// This function destroys the popup when the user clicks the X.
			function destroyPopup(feature) {
				feature.popup.destroy();
				feature.popup = null;
			}

			// This feature connects the click events to the functions defined above, such that they are invoked when the user clicks on the map.
			var selcontrol = new OpenLayers.Control.SelectFeature(lgpx, {
				onSelect: createPopup,
				onUnselect: destroyPopup
			});
			map.addControl(selcontrol);
			selcontrol.activate();

			// Finally, center the map - this will activate the autozoom / autocenter feature.
			if(!map.getCenter())
				map.setCenter(null, null);
		}
	</script>
</head>

<body onload="init();">
	<div style="width:100%; height:100%" id="map"></div>
</body>
</html>