Leaflet deel 3 - NieneB/pzh_web_map GitHub Wiki
In Leaflet deel 3 gaan we WMS en WFS laag toevoegen.
De tegel basemaps die we hiervoor hebben toegevoegd zijn een efficiënt manier om raster achtergrond kaarten te maken. Een andere manier is om de client een bounding box te laten verzenden en deze te laten genereren op de server en als kant en klaar plaatje terug te sturen. Dit noemen we een WMS (Web Map Service). Elke keer als de kaart verschoven word (zoomen of pannen) dan word er een nieuw plaatje opgevraagd en versuurd. Dit is altijd een trade off tussen render snelheid, server opslag ruimte en andere prestatie factoren van je applicatie, server en client.
Het Open Geospatial Consortium (OGC) is een internationaal non-profit organisatie die de standaarden zoals WMS en WFS beheerd.
Bij PDOK en het CBS hebben verschillende WMS en WFS services beschikbaar die voldoen aan de OGC standaarden.
De Provincie Zuid-Holland maakt gebruik van de ESRI diensten. Deze voldoen minimaal aan de OGC standaarden omdat ESRI zijn eigen standaarden heeft.
Heel veel geo data in Nederland kan je vinden op het nationaalgeoregister.nl.
De WMS protocol, vraag elke keer een plaatje op die speciaal gerenderd word voor jou. De server intrepeteert de data voor jouw gebied en past de cartografische stijl toe voordat het plaatje wordt toegestuurd.
Een WMS kent 3 verschillende requests:
- GetCapabilities
- GetMap
- GetFeatureInfo
Met een GetCapabilites
request kan je alle eigen schappen van de Web Map Service bekijken. Welke data lagen er zijn, welke coordinaat systemen er worden onderstuend etc.
De getMap
hebben we hierboven al gebruikt. Hiermee vraag je de plaatjes op van de kaart binnen de opgegeven bounding box. Leaflet zorgt ervoor dat er elke keer de juiste request worden opgestuurd met de benodigde bounding box.
Een png plaatje wat je terug krijgt bevat natuurlijk helemaal geen informatie meer over de objecten op de kaart. Het zijn gewoon gekleurde pixels geworden. Wil je toch een klik actie toevoegen aan de kaart met informatie over het object, dan zul je een getFeatureInfo
request moeten versturen. Dan vraag je de informatie op van een gegeven locatie.
<script>
tags, onder de map
.
// Add WMS layer
var milieulaag = L.tileLayer.wms('http://geoservices.zuid-holland.nl/arcgis/services/Milieu/Milieu_WKO/MapServer/WmsServer?', {
'version': '1.3.0',
'styles': 'default',
'layers': 'Tweede en derde watervoerend pakket',
'format': 'image/png',
'transparent': true,
'srs': 'EPSG:28992',
'opacity': 0.8,
'attribution': '<a href="">Geoservices PZH</a>'
}).addTo(map);
Op het [nationaalgeoregister.nl] kan je vinden welke geo data de provincie allemaal heeft gepubliceerd. Probeer zelf nog een extra data laag te vinden en de WMS url hiervan te achterhelen.
Je kan ook kijken in het overzicht van de ArcGIS server: https://geoservices.zuid-holland.nl/arcgis/rest/services/ Of zoeken in jullie eigen geoportals.
Erg handig hierbij is de GetCapabilities
van een Web Map server op te vragen. Bijvoorbeeld:
Hier vind je alle lagen die beschikbaar zijn in de WMS.
Leaflet heeft een extra opties om de kaart te controleren aan de client side. Om meerdere lagen toe te voegen en zelf aan en uit te zetten bestaat de control.layers
Eerst moeten we meerde lagen definieren:
// Add multiple layers
var pzhkaarten = {
cultuur: L.tileLayer.wms('https://geoservices.zuid-holland.nl/arcgis/services/Cultuur/Cultuurhistorie_Beeldbepalend_Erfgoed/MapServer/WmsServer?', {
'version': '1.3.0',
'styles': 'default',
'layers': 'Historische orientatiepunten.',
'format': 'image/png',
'transparent': true,
'srs': 'EPSG:28992',
'attribution': '<a href="">Geoservices PZH</a>'
}),
milieu: L.tileLayer.wms('http://geoservices.zuid-holland.nl/arcgis/services/Milieu/Milieu_WKO/MapServer/WmsServer?', {
'version': '1.3.0',
'styles': 'default',
'layers': 'Tweede en derde watervoerend pakket',
'format': 'image/png',
'transparent': true,
'srs': 'EPSG:28992',
'opacity': 0.8,
'attribution': '<a href="">Geoservices PZH</a>'
})
};
Nu voegen we de control
toe met onze Provincie Zuid-Holland kaarten:
L.control.layers(pzhkaarten).addTo(map);
Tot nu toe hebben we alleen platte plaatjes opgevraagd. Een andere manier of geografische data op te vragen en ook daadwerkelijk de geografische objecten te krijgen is de WFS protocol.(Web Feature Service). Het stataard response van een WFS request is een GML formaat, een Geografisch XML formaat. Er is ook de optie om een request te laten reageren met een GeoJSON formaat. Een data formaat wat Leaflet goed begrijpt.
Het voordeel hiervan is dat we de stijl van de geografische objecten zelf kunnen aanpassen in de kaart applicatie!
De provincie Zuid-Holland serveert haar data met de ESRI server. Deze serveert de WFS alleen in GML formaat. Kijk maar eens naar de GetCapabilities
van bijvoorbeeld de Cultuurhistorie data.
Om GML in Leaflet te laten zien is erg lastig.
Laten we daarom kijken naar een WFS laag van het CBS die wel GeoJSON request ondersteund.
kijk maar eens naar de WFS getCapabilities van de wijk en buurt kaart:
https://geodata.nationaalgeoregister.nl/wijkenbuurten2018/wfs?&request=GetCapabilities&service=WFS
Hier zie je wel de JSON optie beschikbaar.
var geojson = L.geoJson(null,
{
style: getStyle
}
).addTo(map);
var url = 'https://geodata.nationaalgeoregister.nl/wijkenbuurten2018/wfs?';
Leaflet verwacht de data als GeoJSON. De coördinaten moeten dan in WGS-84 (EPSG:4326) staan. Zo zorg dat je ook deze projectie ook opvraagt.
var params = 'service=WFS&version=2.0.0&request=GetFeature&outputFormat=application/json&srsName=EPSG:4326&';
Daarna moeten we aangeven welke laag we willen opvragen. En we kunnen een filter toevoegen.
params += 'typeName=wijkenbuurten2018:cbs_buurten_2018&';
params += 'propertyName=gemeentecode,gemeentenaam,buurtnaam,geom&';
params += 'cql_filter=gemeentecode \= \'GM0003\'';
Nu moeten we nog een eigen stijl toevoegen aan de features die we binnen krijgen. Je kan deze stijl baseren op een data attribuut. Maar laten we ze eerst allemaal indezelfde kleur zetten.
function getStyle(features) {
return {
color: '#fff',
weight: 0.8,
opacity: 1,
fillOpacity: 0.9
}
}
Nu moeten we het request nog versturen. Hiervoor gebruiken we een XMLHttpRequest()
. Ook dit is een extra library die we aan onze HTML pagina moeten toevoegen:
html
:
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/1.1.1/chroma.min.js"></script>
Let op! Dit is geen Leaflet plugin! Maar een JavaScript library die voor veel meer dingen gebruikt wordt.
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url + params));
xhr.onload = function () {
if (xhr.status === 200) {
geojson.addData(JSON.parse(xhr.responseText));
} else {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send();
Als het goed is zie je nu de buurten van de gemeente Den Haag over de kaart heen getekend!
Bij de features zit al attribuut informatie. We vragen in onze parameters de gemeentecode, gemeentenaam en buurtnaam op. Maar dit kunnen we natuurlijk uitbereiden. Laten we nu een popup toevoegen met de buurtnaam.
params += 'propertyName=gemeentecode,gemeentenaam,buurtnaam,geom&';
bindPopup
event toe aan de GeoJSON.
// WFS
var geojson = L.geoJson(null,
{
style: getStyle
}
).bindPopup(function (layer) {
return layer.feature.properties.buurtnaam
}).addTo(map);
Het is natuurlijk mooier als de stijl van de buurt ook veranderd als je er met je muis overheen beweegt. Dit roept uit tot actie!
We gaan een aantal functies maken.
- Een highlight functie die de kleur naar geel veranderd.
- Een reset functie die de feature weer naar de normale kleur veranderd.
- Een zoom naar feature functie zodat de kaart zich netjes aanpast op de geklikte buurt.
Uiteindelijk stoppen we deze 3 funties weer allemaal in 1 functie zodat het makkelijk is toe te voegen aan de GeoJSON.
// Mouse interaction
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 3,
color: '#eee000',
});
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
}
// Function for reseting highlight
function resetHighlight(e) {
geojson.resetStyle(e.target);
}
// Function to zoom to feature
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
Als laatste moeten we de onEachFeature
nog toevoegen aan de GeoJSON:
onEachFeature
functie in de GeoJSON opties:
// WFS
var geojson = L.geoJson(null,
{
style: getStyle,
onEachFeature: onEachFeature
}
).bindPopup(function (layer) {
return layer.feature.properties.buurtnaam
}).addTo(map);
Als je tevreden bent met je kaart publiceer het dan online!
➡️ Ga naar Hosting op Github