Adding GetFeatureInfo capability
Earlier we issued an additional WMS request called GetLegendGraphic
to show the legend. Similarly, we can use yet another WMS interface standard to retrieve attribute data of the maps by issuing the OGC GetFeatureInfo
request. This involves some more work, because the result will be some arbitrary content that will arrive after an unknown amount of time. To handle this, we will need to use something called Asynchronous JavaScript.
First, we have to prepare MapServer to actually be set up to respond to the request in a way the OpenLayers script can handle:
Edit your .map
file. In each LAYER
object you want to query, put the lines:
TOLERANCE 5 TOLERANCEUNITS pixels
In each LAYER
object's METADATA
put the extra line:
"wms_include_items" "all"
In each CLASS
object put the extra line:
TEMPLATE "empty"
TOLERANCE
and TOLERANCEUNITS
will make sure that an object is considered clicked upon, even if you are up to 5 pixels off. You can change these values if needed. wms_include_items
tells MapServer to show all
attributes it has available. You can change it to a comma-delimited list of attribute names if you want to limit the output.
The TEMPLATE
line is needed for GetFeatureInfo to work, but it does not have to point to an actual template document (that is why we put an "empty" value in there). In that case it will just retrieve the raw text output of MapServer's attribute query. If you want to nicely format the GetFeatureInfo output, you let it point to an actual template HTML file (see the Mapserver documentation for more information on how to use these).
Now edit your html file by adding a third div
element to the HTML lay-out as a placeholder for the query results. See the highlighted line in the listing below.
78 79 80 81 |
</div> <div id="queryresultsDiv" style="position: absolute; width: 250px; height: 395px; left: 420px; top: 210px; overflow: auto; border: 1px solid blue;"> </body> </html> |
We want to have clicks in the map result in a GetFeatureInfo
request to MapServer. Fortunately, we can use existing OpenLayers functionality to achieve that: there is a getGetFeatureInfoUrl
method to create an OGC-compatible request. And we can use an HTML <iframe>
to actually fire the request and retrieve its results, by supplying it with the url constructed by the getGetFeatureInfoUrl
method:
Put the highlighted code in the listing below at the end of the init
function, just before the ending }
character.
Try to understand what it does, read the comments in the code... Test the result in a web browser.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
myMap.setView( //center coords and zoom level: new ol.View({ center: [11219175,1507650], zoom: 5}) ); // add event listener for click events on Map object // if clicked, run the function... myMap.on('singleclick', function(evt) { // first clear the contents of the results div: document.getElementById("queryresultsDiv").innerHTML = ""; // retrieve map resolution details from the map object var viewResolution = myMap.getView().getResolution(); // now create a url with an OGC GetFeatureInfo request: var url = forestLayer.getSource().getGetFeatureInfoUrl( evt.coordinate, viewResolution, 'EPSG:3857', {'INFO_FORMAT': 'text/plain', //format to ask info in 'QUERY_LAYERS': 'forest,railroad,airports'} //layers to ask info for ); // an iframe in the div fires the request and retrieves the results: document.getElementById("queryresultsDiv").innerHTML = '<iframe height="100%" seamless src="' + url + '"></iframe>'; }); } </script> <!--run init script after page body loaded : --> <body onload="init()"> |

OPTIONAL CHALLENGE: More sophisticated querying
As a challenge, try to create a more more sophisticated query system:
In our example above, we retrieved the GetFeatureInfo results as plain text. GetFeatureInfo results can also be provided by MapServer using a sophisticated mechanism of (interactive) templates: The results of queries are then parsed into HTML templates. This allows for example to only show certain attributes, to format the output nicely and even to building of a feedback mechanism, through HTML forms.
An working example of this can be found at this location. Try to see what happens if you query an airport...
More information on the templating can be found in the MapServer documentation at http://mapserver.org/mapfile/template.html
Try to create a more sophisticated query output, where you can retrieve
- the names of airports,
- the class of forest
- the ID of railroads