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.

Een WMS laag toevoegen

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:

  1. GetCapabilities
  2. GetMap
  3. 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.

▶️ Voeg een WMS laag toe aan je kaart. Zet de volgende code tussen de <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.

▶️ Vind zelf een WMS laag en voeg deze toe aan je kaart.

Erg handig hierbij is de GetCapabilities van een Web Map server op te vragen. Bijvoorbeeld:

https://geoservices.zuid-holland.nl/arcgis/services/Milieu/Milieu_WKO/MapServer/WmsServer?&service=WMS&request=getCapabilities

Hier vind je alle lagen die beschikbaar zijn in de WMS.

▶️ Gebruik dezelfde WMS maar voeg een ander laag toe aan je kaart.

Meerdere lagen

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);

WFS

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.

https://geoservices.zuid-holland.nl/arcgis/services/Cultuur/Cultuurhistorie_WFS/MapServer/WFSServer?request=GetCapabilities

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.

▶️ Laten we een WFS geoJSON van de buurten gaan toevoegen.

▶️ Om de data toe te voegen maken we eerst een lege GeoJSON laag aan in ons script:

var geojson = L.geoJson(null,
    {
        style: getStyle
    }
).addTo(map);

▶️ Zet de url van de WFS in het script.

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.

▶️ Zet de parameters voor de WFS request:

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.

▶️ Zet nog meer parameters voor het request

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.

▶️ Zet de stijl in het script

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:

▶️ Zet de script in de 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.

▶️ Verstuur het request in je script:

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!

Feature info

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&';

▶️ Voeg een bindPopup event toe aan de GeoJSON.

// WFS
var geojson = L.geoJson(null,
    {
        style: getStyle
    }
).bindPopup(function (layer) {
        return layer.feature.properties.buurtnaam
}).addTo(map);

▶️ Dat is het! Ververs je browser en klik op een buurt.

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.

  1. Een highlight functie die de kleur naar geel veranderd.
  2. Een reset functie die de feature weer naar de normale kleur veranderd.
  3. 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
    });
}

▶️ Voeg deze 4 functies toe aan je script.

Als laatste moeten we de onEachFeature nog toevoegen aan de GeoJSON:

▶️ Zet de 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

⚠️ **GitHub.com Fallback** ⚠️