Adding WMS of Thailand
We will add a layer to the general OpenStreetMap layer we created earlier, using the Thailand WMS we made earlier in the MapServer exercises:
Create a copy of the html page you made earlier with a different name, e.g. osmPlusWMS.html
and open that copy.
Add the highlighted code lines in the listing below below just after the layer definition you made earlier (for the OSM world map).
Try it out in the browser.
Refer to the earlier MapServer exercises, to know how to substitute the[NETPATH]
for the proper values for your set-up! Also check the use the proper name of the configuration.map
file you used (e.g.config.map
)...!
18 19 20 21 22 23 24 25 26 27 28 29 30 |
source: new ol.source.OSM() }); railroadLayer = new ol.layer.Tile({ source: new ol.source.TileWMS({ url: "https://gisedu.itc.utwente.nl/cgi-bin/mapserv.exe?map=[NETPATH]/config.map&", params: {"LAYERS": "railroad", "TILED": true} }) }); // add layer to map: myMap.addLayer(osmLayer); myMap.addLayer(railroadLayer); // create a map view: myMap.setView( |
Note that the result is not what you might have expected: No Thailand railroad layer to be seen...!
The initial try to combine OSM and WMS failed, because it is not so straightforward as it may seem. The reason for that is the difference in map projection of the layers. The basic OSM layer is using the Web Mercator projection mentioned in the OpenStreetMap introduction. But earlier you did set up the Thailand WMS to serve data in degrees longitude-latitude on the WGS84 datum (EPSG code 4326). We can not change the OSM projection, but a proper WMS should be able to serve its data in any projection that the software supports.
However, we do have to change the set up of the Thailand WMS to allow that, which is very simple actually:
In your WMS configuration (.map
) file, look for the WEB/METADATA
object and find the line: "ows_srs" "EPSG:4326"
and add the Web Mercator projection to the list of allowed projections, like this:
"ows_srs" "EPSG:4326 EPSG:3857"
.
Now try loading the map once again in the browser. You now should have more success...
There is still one annoying problem: The legend you defined in the earlier WMS exercise will be shown several times within the map. This is because OpenLayers uses a tiling mechanism to subdivide the WMS output in many small tiles. Each of these tiles will have a legend, because you did set the LEGEND
object in the configuration file to STATUS EMBED
.
Edit the .map file: Change the LEGEND
object from STATUS EMBED
to STATUS ON
. Reload the web page.
The legend will now disappear, but we will make it appear again in a different way further on.
Enhancing the layout
In order to have a place to put the legend in, we will make a more sensible layout than the one we had earlier. You can change the layout by setting the style properties of the separate place-holder in HTML. Many HTML elements can be used as place-holders, we simply used a <div>
element.
Change the line defining the div
<div id="mapDiv" style="width: 400px; height: 400px;">
to the higlighted line in the listing below. You should play around with the parameter values to see the styling changes.
52 53 |
<!--map placeholder div: --> <div id="mapDiv" style="position: absolute; left: 5px; top: 5px; width: 400px; height: 600px; overflow: hidden; border: 1px solid blue; "></div> |
The style properties are expressed using CSS (Cascading Style Sheets), a styling language standardised by the W3C, the World Wide Web Consortium. The meaning of the properties used is:
- position: this lets you define positioning:
absolute
orrelative
to other divs. - left & top: the (absolute) location with respect to the upper left corner of the window
- width & height: the size of the element (in pixels)
- overflow: if the content is larger than fits the div, it will not be shown if this is set to
hidden
. Other settings arevisible
(will overflow),scroll
(will make scrollbars) andauto
(let browser decide). - border: the border look (line width, type and colour). You can also set the
fill
in a similar way.
For those already familiar with CSS styling: You can of course also define the styles in the standard CSS way, by defining a named class in a CSS file, and referring to that class in the HTML code in the standard way: <div id="mapDiv" class="yourClassName">
Adding the legend
Now you can add another part to the layout that will hold the legend for the Thailand WMS layers. Add a second <div>
element for the legend, and inside this create an HTML <img>
element, as shown in the highlighted lines in the listing below.
52 53 54 55 56 57 58 59 |
<!--map placeholder div: --> <div id="mapDiv" style="position: absolute; left: 5px; top: 5px; width: 400px; height: 600px; overflow: hidden; border: 1px solid blue; "></div> <div id="legend" style="position:absolute; width:250px; height:200px; left: 420px; top: 5px; overflow: auto; border: 1px solid blue; "> <img align="middle" src="https://gisedu.itc.utwente.nl/cgi-bin/mapserv.exe?map=[NETPATH]/config.map&SERVICE=WMS&VERSION=1.3.0&SLD_VERSION=1.1.0&REQUEST=GetLegendGraphic&FORMAT=image/png&LAYER=railroad"> <br/> </div> </body> </html> |
This should result in the railroad layer legend being shown in the legend div
. The src=
parameter of the img
tag issues a new OGC WMS request called GetLegendGraphic
. This request retrieves from the WMS the legend of a LAYER
, requested as an image, in the image FORMAT
specified.
Note thatGetLegendGraphic
is an optional OGC-WMS request, our MapServer installation does support it, but not all WMS services do! Note also that for each layer, you will have to do a separateGetLegendGraphic
request...!
Adding more layers
Now add other layers of the Thailand WMS: forest and airports. You should be able to figure out how to do that based on the previous tasks.
Do not forget legend entries for these layers, and note that the order in which you add the layers with the myMap.addLayer()
method is important!
Now we have more than one layer, it would be useful to control which of those are shown in our map. So we will add some layer control:
Just before the <img>
tag that displays the legend entry for the forest layer, add the line :
<input type="checkbox" checked onchange="forestLayer.setVisible(!forestLayer.getVisible())">
A small checkbox control should have been added to the legend entry that lets you toggle the visibility of the forest layer. Try to understand how this works: It is a combination of an HTML form element (a checkbox
) that triggers (by the onchange
event trigger) a little javascript (inside the string that is the onchange parameter). This script reads (getVisible
) the boolean visibility setting of an OpenLayers Layer
object, and then changes it (setVisible
) to its boolean opposite... In javascript, the logical operator NOT is expressed with the !
-symbol.
Once you understand the methodology, you should be able to add toggle switches for the other layers.