Webkort med Leaflet.js

Workshop

Karen Frederiksen
kaf@jammerbugt.dk
LinkedIn
@FrkFilur
Niels Kjøller Hansen
niha07@frederiksberg.dk
linkedin.com/in/nielskjoller
@nkjoller

Følg med på http://lab.kjlr.dk/slides/leaflet-workshop/

Fredninger i Jammerbugt Kommune

Fredninger i Jammerbugt Kommune

Leaflet

Et javascript-bibliotek til at lave smidige web-kort

  • Fylder 33kb komprimeret
  • Mindre funktionalitet er en feature
  • Tusind plugins

Hvordan?

  1. Hent pakke fra http://leafletjs.com/
  2. Importer javascript og css
  3. Tilføj et html-element til kortet
  4. Sæt kortets størrelse op til hvad du ønsker
  5. Tilføj et baggrundskort

HTML-siden

Importer javascript og css

<link rel="stylesheet" 
  href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

Tilføj et kort-element (og angiv størrelse)

<div style="width: 600px; height: 300px;" id="map"></div>

Javascript-siden

Sæt kortet på kort-elementet

var map = L.map('map').setView([55.65,12.543]);

Tilføj et baggrundslag til kortet

L.tilelayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; OpenStreetMap'
}).addTo(map);

Gør noget fedt!

// Tilføj en markør til kortet
L.marker([55.6505,12.543]).addTo(map)
    .bindPopup('Fed markørinfo')
    .openPopup();

Demo

Og hvad så?

Fredninger i Jammerbugt Kommune

Fredninger i Jammerbugt Kommune

Aflevering af affald i Frederiksberg Kommune

Fredninger i Jammerbugt Kommune

Tid til øvelser

Zip-fil med alt det grej du skal bruge.

Øvelse 1: Få Kongskilde ind i kampen

Vi starter her, et tilfældigt sted i Smørum Nedre: http://kosgis.kjlr.dk/~kosgis/leaflet/oevelse1.html

Opgaven er:

  • Centrer kortet, og flyt markøren til hvor vi er (koordinatet er 55,37541 grader nord, 11,53923 grader øst).
  • Ændr teksten til noget passende
  • Skift ikonet ud med fx. et KOSGIS-logo

Hints:

Zoom-niveau og centerpunkt sættes i denne linje:

var map = L.map('map').setView([55.738,12.3],17);

Punktet laves i denne linje:

L.marker([55.37641,11.53923])

Popup-teksten her:

.bindPopup('Fed markørinfo')

Skift ikonet ud - sådan gør du

Først skal du have defineret et ikon. Det er lidt bøvlet:

var kosgis_icon = L.icon({
   iconUrl:      'img/kosgis_marker.png',
   shadowUrl:    'img/kosgis_skygge.png',
   iconSize:     [45,50],
   shadowSize:   [55,35],
   iconAnchor:   [16,49], 
   shadowAnchor: [11,33], 
   popupAnchor:  [8,-40]  
});

Derefter kan du sætte det på når markeren bliver lavet:

L.marker([lat,lng]>, {icon: kosgis_icon})

Det kunne se sådan ud

http://kosgis.kjlr.dk/~kosgis/leaflet/oevelse1-facit.html

Øvelse 2: Find dig selv, find andre

Vi starter med noget vi har set før:
http://kosgis.kjlr.dk/~kosgis/leaflet/oevelse2.html

Opgaven er:

  • Tilføj plugin der kan finde din nuværende position.
  • Tilføj plugin til adressesøgning
  • Udvid adressesøgnings-plugin til at bruge DAWA

For ikke at spilde tid, så er relevant javascript og CSS til plugins allerede skrevet ind i "oevelse2.html"

Locate-plugin

https://github.com/domoritz/leaflet-locatecontrol

Man skal loade relevant javascript og css:



Derefter kan kontrolvinduet oprettes og tilføjes til kortet:

L.control.locate().addTo(map);

Adressesøgning

https://github.com/perliedman/leaflet-control-geocoder

Ikke nødvendigvis det lækreste, men til gengæld er koden god og relativt nem at udvide.

Javascript og css indlæses:


Derefter kan kontrolvinduet oprettes og tilføjes til kortet:

L.Control.geocoder().addTo(map);

DAWA-modul til adressesøgning

https://github.com/kjoller/leaflet-control-geocoder-dawa

Javascript og css indlæses:

Derefter kan man udvide oprettelsen af geokoderen (+ lidt ekstra):

L.Control.geocoder({
   position:'topleft',
   placeholder: 'Søg adresse',
   errorMessage: 'Intet fundet',
   geocoder:  new L.Control.Geocoder.dawa({
      geocodingQueryParams: {kommunekode: '0340'},
      wildcard: true
   })
}).addTo(map);

Mulig løsning:

http://kosgis.kjlr.dk/~kosgis/leaflet/oevelse2-facit.html

Øvelse 3: Nu med rigtig data

Vi fortsætter hvor vi slap:
http://kosgis.kjlr.dk/~kosgis/leaflet/oevelse2.html

Opgaven er:

  • For at undgå forvirring tilføjes en lagkontrol
  • Sæt Sorøs fortidsminder på kortet (data/fortidsminder.geojson).
  • Lav popups med attribut-data
  • Tematiser efter attribut-data med farvede cirkler efter fortidsmindernes datering


At indlæse data fra fx GeoJSON kan gøres vha. jQuery. Nedenstående linje er allerede skrevet ind i "oevelse3.html":

En lagkontrol

En lagkontrol er indbygget i Leaflet og indsættes således

var layercontrol = L.control.layers(baggrundslag,overlays).addTo(map)

Det er et krav at man har lagene som variable, så derfor erstattes

 L.marker([55.376,11.539], {icon: kosgis_icon}).addTo(map)

med

var kosgis = L.marker([55.376,11.539], {icon: kosgis_icon})

Derved kan man henvise til laget, og lave parameteren

var overlays = {
          'KOSGIS workshop': kosgis
      }

Noget tilsvarende kan gøres med baggrundslaget, men er ikke strengt nødvendigt, da vi kun har ét

Indlæs GeoJSON

Et standard jQuery-kald ser ud ca således:

$.get(url, function(data) {
   // gør noget med data når de er hentet...
}, format ); //format kunne være 'json'

Man kan tilføje en GeoJSON til et kort ved at lave:

var minepunkter = L.GeoJSON(data,options).addToMap()

Hvis man vil lave punktlag, så er option 'PointToLayer' vigtig. Det er en funktion, der for hvert punkt skal returnere et marker-objekt, fx:

pointToLayer: function(feature, latLng) { 
   return new L.marker(latLng) // en standard-marker på punktets koordinat
]

GeoJSON - fortsat

Det kan sættes sammen med vores data til:

$.get('data/fortidsminder.geojson', function(data) {
    var fortidsminder = new L.GeoJSON(data, {
        attribution: '© Kulturarvsstyrelsen',
         pointToLayer: function(feature, latLng) {
             return new L.marker(latLng)
         }
    }).addTo(map);
    layercontrol.addOverlay(fortidsminder,'Fortidsminder');
}, 'json');

Læg mærke til hvordan laget tilføjes til lagkontrollen til sidst

Mange popups!

Tricket er at tilføje en popup (kan I huske det?) på hver enkelt. Til det er der en option til L.GeoJSON, der hedder "onEachFeature", hvor man definerer en funktion, der skal køres på alle features. Eksempel:

onEachFeature: function(feature,layer) {
    layer.bindPopup('Her er en popup!')
}

Læg mærke til at bindPopup kaldes på layer. feature er udelukkende data, hvor layer refererer til det éne punkt man har fat i på nuværende tidspunkt

Fat i attributter

Man kan få fat i attributter i 'feature', mere specifikt i 'feature.properties'.

For at få at lave en popup med fortidsmindets datering kunne man:

layer.bindPopup(feature.properties.datering)

Andre relevante felter kunne være 'url' eller 'anlaegstyp'

Tematisering

Istedet for at lave ikoner til alle forskellige dateringer, bruges istedet L.circleMarker. En L.circleMarker er ligesom en L.marker, bortset fra at den er en cirkel, der kan gives en farve.

var mitpunkt = L.circleMarker([lat,lng],{color: blue});

Man kan tematisere i pointToLayer-funktionen, fx med en javascript switch:

pointToLayer: function(feature, latLng) {
    switch (feature.properties.datering) {
        case 'Stenalder': return L.circleMarker(latLng, {color: black});
        case 'Bronzealder': return L.circleMarker(latLng, {color: red});
        // ...
        default: return L.circleMarker(latLng,{color:white});
    }
}

Der findes følgende typer datering i data: Stenalder, Bronzealder, Oldtid, Vikingetid, Middelalder, Historisk Tid, Nyere tid, Udateret

Frederiksbergs nye borgervendte kort

Et billede af et flot kort

Find rundt på Rådhuset

Rådhuset

>Gode steder