OpenLayers osm file example

From OpenStreetMap Wiki
Jump to navigation Jump to search

OpenLayers has some built-in support for .osm files. It will automatically convert elements into a vector layer display.


Running example


To run the example code

  • Copy and paste the code below into a fresh new file. Call it 'myexample.html'
  • Copy and paste the example OSM XML into a fresh new file. Call it 'myosmfile.osm'
  • Double click 'my example.html' to open it as local file in your favourite web browser.

This works in firefox, and safari. Not tested in IE (FIXME). In chrome this doesn't work locally due to javascript security restrictions, but it does when you come to run this from the web. Upload both files to a web server somewhere.

Put this in a .html file

<html>
    <head>
        <title></title>
        <script src="http://openlayers.org/api/OpenLayers.js"></script>
        <script type="text/javascript">
            var lat=34.070;
            var lon=-118.73;
            var zoom=15;
            var map;
 
            function init(){
                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")
                } );
 
                
                map.addLayer(new OpenLayers.Layer.OSM());
 
                var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
 
                map.setCenter (lonLat, zoom);

                //Initialise the vector layer using OpenLayers.Format.OSM
                var layer = new OpenLayers.Layer.Vector("Polygon", {
                    strategies: [new OpenLayers.Strategy.Fixed()],
                    protocol: new OpenLayers.Protocol.HTTP({
                        url: "myosmfile.osm",   //<-- relative or absolute URL to your .osm file
                        format: new OpenLayers.Format.OSM()
                    }),
                    projection: new OpenLayers.Projection("EPSG:4326")
                });
 
                map.addLayers([layer]);
 
            }
        </script>
    </head>
    <body onload="init()">
        <div id="map" class="smallmap"></div>
        </div>
    </body>
</html>

This is the code to do the same with Openlayers 3 and newer.

<html>
	<head>
		<title>OpenLayers 3+ .osm File Example</title>
		
<script src="https://cdn.jsdelivr.net/npm/ol@v8.1.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v8.1.0/ol.css" />
<script src="https://unpkg.com/ol-layerswitcher@4.1.1/dist/ol-layerswitcher.js"></script>
<link rel="stylesheet" href="https://unpkg.com/ol-layerswitcher@4.1.1/dist/ol-layerswitcher.css" />

		<script type="text/javascript">
			var lat=34.070;
			var lon=-118.73;
			var zoom=15;
			let osmFile = 'display-osm.osm';


function init(){																			 
	var map, layer, center;																	
	map = new ol.Map({																	 
		target:'map',																	
		renderer:'canvas',															 
		view: new ol.View({															
			projection: 'EPSG:900913',											 
		})																		 
	});																				
	const baseOSM = new ol.layer.Tile({															
		title: 'baseOSM',
		source: new ol.source.OSM()													
	});																				
	map.addLayer(baseOSM); // this can actually come up last								 
	center = new ol.proj.transform(
		[lon, lat],
		'EPSG:4326', // essentially LonLat						
		map.getView().getProjection()
	);						 
	map.getView().setCenter(center);														 
	map.getView().setZoom(zoom);																
	const formatOSM = new ol.format.OSMXML();
	const vectorSource = new ol.source.Vector({
		format: formatOSM,
		loader: function (extent, resolution, projection, success, failure) {
			const epsg4326Extent = ol.proj.transformExtent(extent, projection, 'EPSG:4326');
			fetch(osmFile).then(reply => {
				reply.text().then(replyText => {
					const features = formatOSM.readFeatures(replyText, {
						featureProjection: map.getView().getProjection(),
					});
					vectorSource.addFeatures(features);
					success(features);
				});
			}).catch(failure);
		},
		strategy: ol.loadingstrategy.fixed,
	});
	
	const dim_orange = ol.color.asString(
		ol.color.asArray('orange').slice(0, 3).concat(0.1));
	const localOSM = new ol.layer.Vector({
		title: 'localOSM',
		source: vectorSource,
		style: new ol.style.Style({
			stroke: new ol.style.Stroke({
				color: 'orange',
				width: 1,
			}),
			fill: new ol.style.Fill({
				color: dim_orange,
			}),
			image: new ol.style.Circle({
				fill: new ol.style.Fill({
					color: dim_orange,
				}),
				radius: 6,
				stroke: new ol.style.Stroke({
					color: 'orange',
					width: 1,
				}),
			}),
		}),
	});
	
	map.addLayer(localOSM);
	let layerSwitcher = new ol.control.LayerSwitcher({
		tipLabel: 'Légende' // Optional label for button
	});
	map.addControl(layerSwitcher);
}
		</script>
	</head>
	<body onload="init()">
		<div id="map"></div>
		<div id="explanation">OpenLayers displaying a .osm file directly. This <a href="display-osm.osm">display-osm.osm</a> is a very small example. Most .osm files would be too large to do this, and in general you're more likely to load in vector features in a different way</div>
	</body>
</html>

Put this in myosmfile.osm

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' generator='JOSM'>
  <bounds minlat='34.0662408634219' minlon='-118.736715316772' maxlat='34.0731374116421' maxlon='-118.73122215271' origin='OpenStreetMap server' />
  <node id='358802885' timestamp='2009-03-11T06:30:08Z' user='yellowbkpk' visible='true' version='1' lat='34.0666735' lon='-118.734254'>
    <tag k='gnis:created' v='06/14/2000' />
    <tag k='gnis:county_id' v='037' />
    <tag k='name' v='Santa Monica Mountains National Recreation Area' />
    <tag k='leisure' v='park' />
    <tag k='gnis:feature_id' v='277263' />
    <tag k='gnis:state_id' v='06' />
    <tag k='ele' v='243' />
  </node>
  <node id='453966480' timestamp='2009-08-02T03:36:00Z' user='Apo42' visible='true' version='1' lat='34.07234' lon='-118.7343501' />
  <node id='453966482' timestamp='2009-08-02T03:36:01Z' user='Apo42' visible='true' version='1' lat='34.0670965' lon='-118.7322253' />
  <node id='453966143' timestamp='2009-08-02T03:35:45Z' user='Apo42' visible='true' version='1' lat='34.0724577' lon='-118.7364799' />
  <node id='453966130' timestamp='2009-08-02T03:35:44Z' user='Apo42' visible='true' version='1' lat='34.0671122' lon='-118.7364725' />
  <node id='453966490' timestamp='2009-08-02T03:36:02Z' user='Apo42' visible='true' version='1' lat='34.0722227' lon='-118.7322321' />
  <way id='38407529' timestamp='2009-08-02T03:37:41Z' user='Apo42' visible='true' version='1'>
    <nd ref='453966480' />
    <nd ref='453966490' />
    <nd ref='453966482' />
    <nd ref='453966130' />
    <nd ref='453966143' />
    <nd ref='453966480' />
    <tag k='park:type' v='state_park' />
    <tag k='csp:unitcode' v='537' />
    <tag k='admin_level' v='4' />
    <tag k='name' v='Malibu Creek State Park' />
    <tag k='csp:globalid' v='{4A422954-089E-407F-A5B3-1E808F830EAA}' />
    <tag k='leisure' v='park' />
    <tag k='attribution' v='CASIL CSP_Opbdys072008' />
    <tag k='note' v='simplified with josm to reduce node #' />
    <tag k='boundary' v='national_park' />
  </way>
</osm>

Extending this example

Of course you can use your own OSM file. e.g. using JOSM to download a little bit of data. Simply save from JOSM to overwrite myosmfile.osm. Keep it small. Too many elements and it will load too slowly in the browser.

It may be possible to access various data in the tags e.g. to make it pops up with details when you click on elements.

This example shows native .osm support within OpenLayers, but for complex projects it may not be the best approach. You might instead convert OSM data into KML for example, then follow OpenLayers KML examples, or you might add elements one by one onto a vector layer (think of it as converting osm format into javascript commands)