Extended GeoAPI tutorial

This tutorial will focus on more advanced features of the GeoAPI, such as the map toolbar, search, and layer management functionality. You should have completed the Basic GeoAPI tutorial before doing this one. The GeoAPI makes extensive use of the Mapfish/GeoExt/Ext framework to offer such advanced functionality. For this example, only very basic understanding of the layout functionality of Ext is assumed.

Creating a Map Panel

We start again with the basic html structure, including the relevant script files for the GeoAPI inside our html file. Please note that we now make use of the Ext.onReady() method to initialize the script only when the page is ready. Inside the .onReady function declaration, we can again start off with the coordinate conversion helper code, before using the .createMapPanel GeoAPI method. This is slightly different to the .createMap function, as it creates an GeoExt Panel to be inserted into another Ext Panel at a later stage.

<html>
 <head>
  <title>Extended example of the GeoAPI</title>
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/build/latest/ext-all.css" />
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/build/latest/xtheme-gray.css" />
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/build/latest/api.css" />
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/build/latest/MapFishApi_api.css" />
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/build/latest/geoadmin.css" />
<link rel="stylesheet" type="text/css" href="//api.geoportail.lu/css/main.css" />
<script type="text/javascript" src="//api.geoportail.lu/build/latest/ext-base.js"></script>
<script type="text/javascript" src="//api.geoportail.lu/build/latest/ext-all.js"></script>
<script type="text/javascript" src="//api.geoportail.lu/build/latest/geoadmin.js"></script>
<script type="text/javascript" src="//api.geoportail.lu/api.js"></script>
   </head>
  <body>
   <div id='map'/>
   <script type="text/javascript">   
		Ext.onReady(function(){
		   lux = new OpenLayers.Projection("EPSG:2169"); // the luxembourg coordinate reference system 
		   wgs = new OpenLayers.Projection("EPSG:4326"); // the WGS84 coordinate reference system, as used widely
		   lonLat = new OpenLayers.LonLat(6.12459923192738, 49.6188206257115 ).transform( wgs, lux );
		   geo = new geoadmin.API({lang: 'fr'});	
                   var mapPanel = geo.createMapPanel({
		      mapInfo: {
			zoom: 8,
			easting: lonLat.lon,
			northing: lonLat.lat,
			bgLayer: 'pixelmaps-gray',
			bgOpacity: 0 
		      }
		   });	
                ...
		});		
	</script>
  </body>
</html>

After having created the mapPanel, we can now create the toolbar, which contains a base layer control, search and history functionality (using the “MapOpacity” parameter). You have to create this after instantiating through .createMapPanel() a Map Panel. Using Ext.apply(), we can then link the toolbar we created to the mapPanel, to arrive at a map window.

Base Layer, History and Search Bar

...
var mapPanel = geo.createMapPanel({
	mapInfo: {
		zoom: 8,
		easting: lonLat.lon,
		northing: lonLat.lat,
		bgLayer: 'pixelmaps-gray',
		bgOpacity: 0 
	}
});
 
//You can't define and link the toolbar before the MapPanel!
geo.searchUrl="//api.geoportail.lu/locationsearch"; 
var toolbar = geo.createToolbar(["MapOpacity"]);
var mapWindow = Ext.apply(mapPanel, {tbar: toolbar});
...

Finally, we need to render our mapWindow in a Ext.Panel object, with the border layout type. Here we use the renderTo property to render the finished panel in the Div. The items property contains an array of elements, in this case the mapWindow. We need to tell the panel though in what region to render the Map Window, in this case “center” (any border layout panel always needs to have at least one element in the center region).

...
var panel = new Ext.Panel({
	id: "geoAPIPanel",
	layout: "border",
	renderTo: "map",
	height: 400,
	width: 700,
	items: 	[Ext.apply(mapWindow, {region: "center"})]
});	
...

This gives us the following map:

Adding a Layer Tree

In the previous tutorial, we saw how to add layers. In order for the user to be able to manage these overlays, a Layer Tree control can be added to our previous example.

In the code below, we add a few layers using the .addLayer() method, and then instantiate a Layer Tree using the .addLayerTree() method.

...
Ext.onReady(function(){
	lux = new OpenLayers.Projection("EPSG:2169"); // the luxembourg coordinate reference system 
	wgs = new OpenLayers.Projection("EPSG:4326"); // the WGS84 coordinate reference system, as used widely
	lonLat = new OpenLayers.LonLat(6.12459923192738, 49.6188206257115 ).transform( wgs, lux );
	geo = new geoadmin.API({lang: 'fr'});
 
	var mapPanel = geo.createMapPanel({
		mapInfo: {
			zoom: 8,
			easting: lonLat.lon,
			northing: lonLat.lat,
			bgLayer: 'pixelmaps-gray'
		}
	});
	//You can't define and link the toolbar before the MapPanel, thus we need to apply tbar property to MapPanel after creation ! 
	var toolbar = geo.createToolbar(["MapOpacity"]);
	var mapWindow = Ext.apply(mapPanel, {tbar: toolbar});
 
	//Add a layerTree control 
	var layerTree = geo.createLayerTree();
 
	geo.addLayerToMap('roads');
	geo.map.getLayersBy('layername','roads')[0].setVisibility(true);
	geo.addLayerToMap('roads_labels');
	geo.map.getLayersBy('layername','roads_labels')[0].setVisibility(true);
	geo.addLayerToMap('addresses');
	geo.map.getLayersBy('layername','addresses')[0].setVisibility(false);
	geo.addLayerToMap('arrets_bus');
	geo.map.getLayersBy('layername','arrets_bus')[0].setVisibility(false);
 
	var panel = new Ext.Panel({
		id: "geoAPIPanel",
		layout: "border",
		renderTo: "map",
		height: 400,
		width: 960,
		items: 	[	Ext.apply(mapWindow, {region: "center"}), 
					Ext.apply(layerTree, {region: "west", width: 280}) 	
				]
	})			
 });
...

Creating Feature Information Popups

Many data layers have the ability to present more information to the user if he clicks on an item. In this example, we will make use of the layer “arrets_bus”. For each bus stop, we want to be able to click on them, and a window will popup giving more information about this bus stop, for example to plan a route from or too this bus stop using public transport.

The code to get this functionality is very simple. You just call the method .createTooltipFeature(). See example below:

...
geo.addLayerToMap('arrets_bus');
geo.map.getLayersBy('layername','arrets_bus')[0].setVisibility(true);
 
geo.createTooltipFeature({
	tooltipUrl:'//api.geoportail.lu/bodfeature/search',
	requestOnlyVisibleLayers:true
});
...

Please note that we need to tell the GeoAPI the address of the tooltip data server, which will deliver the content for a given tooltip, as well as set requestOnlyVisibleLayers:true to make sure that hidden layers can't be queried.

Note also that while we can query the bus stops, if we switch on the address layer, we can also click on individual addresses and get an information popup giving more details about that address. The .createTooltipFeature() method thus is generic and applies in this case to all visible layers added to the map, if they have relevant information that can be queried! Please check the layers list to see which other layers offer this functionality.

Recenter map on specific layer feature

We can also tell the API to center the map on a specific feature of a specific layer, and highlight that object. Again, this is a generic method applicable to all layers which can be queried!

...
geo.addLayerToMap('arrets_bus');
geo.createTooltipFeature({
	tooltipUrl:'//map.geoportail.lu/bodfeature/search',
	requestOnlyVisibleLayers:true
});
geo.showFeatures('arrets_bus',200415006);
...

Including a MyMaps Layer

The MyMaps functionality of the Geoportail allows users to create their own layers of geodata, including points, lines and polygons. Examples include walking trails, Points of Interest and specific zones. The resulting data layers can be published on the geoportail, but can also be included trough the GeoAPI.

To create such a layer through the GeoAPI, you can use the .createMyMapLayer() method. You need to initialise the method with the MyMap ID of the layer you want to include. Also, you can provide a callback function to call once the features are loaded. This proves useful if you want to for example, zoom the map extent to the first node of a path in the MyMapsLayer loaded.

...
function cb(features){
	var c = features.features[0].geometry.getCentroid();
	geo.map.setCenter([c.x,c.y]);
};
geo.createMyMapLayer({mapId:'cf12fe433afa448bb6f3f47b4621127f',callback:cb});
...

A particular feature of the MyMapsLayer is the ability to create a height profile for a given path, and display this alongside the map. Normally, this window is displayed once the user clicks on the path, and selects “View Profile” in the Popup Window. You can force the display of the height profile, either as a popup, or inside a specified Div, using the .showProfile() function:

...
function cb(features){
	var c = features.features[0].geometry.getCentroid();
	geo.map.setCenter([c.x,c.y]);
	geo.showProfile({feature:features.features[0],renderProfileWindowTo:'profileWindow'});
};
geo.createMyMapLayer({mapId:'cf12fe433afa448bb6f3f47b4621127f',callback:cb});
...

Include an external Vector layer

So far, all the functionality presented in this tutorial made use of the GeoAPI. In order to add an external data layer though, we can make use of the functionality of the underlying OpenLayers API. For example, to load a Vector KML file, we will use only OpenLayers functionality. One important note is that the layer property bodid needs to be set (normally using the layer id), for the layer tree to work properly with external vector data sources.

The following example will load the Highway Monitoring Authority road segments KML file, as well as a KML file with the locations of surveillance cameras.

...
var kmlTroncons = new OpenLayers.Layer.Vector("Troncons de Route", {
	projection: new OpenLayers.Projection("EPSG:4326"),
	strategies: [new OpenLayers.Strategy.Fixed()],
	protocol: new OpenLayers.Protocol.HTTP({
		url: "troncons.kml?t=",
		format: new OpenLayers.Format.KML({
			extractStyles: true, 
			extractAttributes: true,
		})
	})
});
kmlTroncons.bodid = kmlTroncons.id;
geo.map.addLayer(kmlTroncons);
 
var kmlCameras = new OpenLayers.Layer.Vector("Cameras CITA", {
	projection: new OpenLayers.Projection("EPSG:4326"),
	strategies: [new OpenLayers.Strategy.Fixed()],
	protocol: new OpenLayers.Protocol.HTTP({
		url: "cameras.kml?t=",
		format: new OpenLayers.Format.KML({
			extractStyles: true, 
			extractAttributes: true,
		})
	})
});
kmlCameras.bodid = kmlCameras.id;
geo.map.addLayer(kmlCameras);
...

In a second step, we can add interactivity to the Cameras KML Data, by specifying an OpenLayers.SelectFeature Control, defining what should happen when the user selects a feature. Two events, onFeatureSelect and onFeatureUnSelect, define a Ext Popup to open and fill with content from the feature attributes when the user selects a feature.

...       
var selectControl = new OpenLayers.Control.SelectFeature(kmlCameras, {
        //hover: true,
        onSelect: onFeatureSelect,
        onUnselect: onFeatureUnselect
});
geo.map.addControl(selectControl);
selectControl.activate();
 
function onFeatureSelect(event) {
    var content = event.attributes.description;
                popup =  new GeoExt.Popup({
                             map: this.map,
                             location: event.geometry,
                             title: event.attributes.name ,
                             width: 200,
                             html: content,
                             collapsible: false,
                            unpinnable: false
                        });
         popup.show();
};
 
function onFeatureUnselect(event) {
    if(popup) {
        popup.destroy();
        delete popup;
    }
};
...

en/api/extendedtutorial.txt · Last modified: 2017/03/02 13:27 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0