En exempelapplikation i Leaflet
Vi ska nu titta på hur man kan skapa en liten applikation baserad på Leaflet. Vi kommer att hämta data från Örebros projekt som tillhandahåller Öppen data. Här finns en hel del trevlig information att tillgå. Vi ska titta på hur man kan läsa ut intresseplatser i Örebros kommun och visa upp dessa på en karta. Även om du inte kommer ifrån Örebro, så är detta en intressant uppsättning av data som passar utmärkt att använda i demosyfte. En fördel med Örebros data är att man supportar CORS och att det därför går att hämta ned data från klientbaserade webbapplikationer.
Vi ska bygga upp vår applikation i steg. Vi kommer att utföra sakerna ungefär i den ordning och med det upplägg som man skulle haft om man gjort detta på "riktigt". Förhoppningsvis blir det lättare att hänga med då.
Vi kommer att använda Codepen-exempel, då dessa ser bra ut och är lätta att lägga in i Webbling. Dock så vill man förstås skriva lite annorlunda om man gör en "riktig" applikation. I slutet kommer vi att länka till den färdiga applikationen, så som den kan köras fristående.
En grund att stå på
Vi börjar med att skapa en grundstruktur för vår sida.
HTML
Det viktigaste vi behöver göra i HTML:en är att lägga till Leaflet, då vi kommer att behöva denna för vår app. HTML:en kan då bli att se ut så här:
Det finns nog inget som förtjänar att kommenteras i den lilla HTML-snutten, då det i stort sett påminner om våra tidigare exempel.
I följande exempel kommer vi att minimera HTML-koden på Codepen, så all kod kommer inte att vara med i HTML-editorn. Allt i föregående exempel behövs dock om du ska skapa applikationen som en fristående webbsajt.
CSS
Vi lägger även till basal CSS:
I CSS:en så startar vi med en minimal reset som gör att vi får ungefär samma grundutseende i alla webbläsare. Vi tar bort alla marginaler, all utfyllnad och ser till att vi använder oss av den "vettiga" boxmodellen.
Då det är tänkt att det mesta i appen ska vara centrerat, så sätter vi att titeln i vår h1
ska vara centrerad.
Det intressantaste vi gör i CSS är det som återfinns i #karta
. Vi sätter höjden till 75vh
. Det vill säga cirka 75 % av skärmens höjd. Se "Måttenheter i CSS", om du glömt hur dessa fungerar. Vi sätter samma proportioner även för bredden. Vi använder oss av margin: 0 auto;
för att centrera vår kart-div
. Slutligen sätter vi en kant runt om kartan.
Lägga till en karta på prov
För att se om kartan fungerar bra ska vi lägga till en testversion av kartan. Vi kör samma kod som i vårt tidigare exempel där vi visade en karta centrerad kring Soltorgsgymnasiet. Vi ändrar dock koordinaterna så att kartan kommer att centreras kring Örebro.
Koden blir att se ut så här:
Resultatet ser ju helt acceptabelt ut och vi får automatisk den grundläggande navigerings-funktionalitet som man förväntar sig av en kartapplikation.
Första försök med att läsa in data
För att gå vidare behöver vi koppla data till vår karta.
Eftersom många API:er har satt gränser för hur ofta man får läs in data ifrån dem, kan det vara en bra idé att jobba lite annorlunda på experimentstadiet. Man tar helt enkelt och hämtar hem en datamängd från källan och sparar denna lokalt. Under testandet så använder du sedan denna undansparade data istället för att hämta hem den gång på gång. Det duger ju gott med denna typ av lagrad data medan vi håller på att slå fast hur layout och liknande ska se ut.
Experimentdata
Vi hämtade ned lite experimentdata ifrån https://karta.orebro.se/api/v1/layers/1?srs=EPSG:4326
. Därefter snyggade vi upp datan genom att köra den genom en JSON-formatterare. Nu när vi ska börja att experimentera är det ju bra om vår data är så läsbar som möjligt. För koden spelar det ingen roll hur data är formaterad och det kommer inte att behövas göra några ändringar för detta.
Vi kortade även ned datamängden så att enbart två kartpunkter är med. Det räcker för experimentsyfte och tar inte så mycket plats. Så här blev vår data att se ut:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
15.253840371567572,
59.277180434995095
]
},
"properties":{
"title":"Alnängsbadet",
"description":"",
"url":"http://www.orebro.se/3089.html",
"rel":"http://karta2.orebro.se/api/v1/information/1"
}
},
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
15.74236626384993,
59.1363775662748
]
},
"properties":{
"title":"Dimbobaden",
"description":"",
"url":"http://www.orebro.se/3090.html",
"rel":"http://karta2.orebro.se/api/v1/information/2"
}
}
]
}
Denna data är i en specialversion av JSON som är till för just kartdata. Den kallas för GeoJSON.
Varje intressepunkt har två delar. Först kommer koordinaterna och sen information om intressepunkten. Vi kommer att bry oss i koordinaterna och title
till att börja med.
Leaflet och GeoJSON
Leaflet har inbyggt stöd för GeoJSON. Om vi använder oss av detta kommer vi att bespara oss själva en hel del arbete. Faktum är att Leaflet kan hantera vår datamängd i det närmaste helautomatiskt. Den kommer att plöja igenom datan och lägga ut den på kartan åt oss. Detta sker utan att vi behöver behandla datan eller skriva några loopar för att gå igenom den.
Vi lägger datamängden i slutet av vår JavaScript-kod, så vi slipper att se den. Sen ska vi skapa lite kod som kan hantera vår GeoJSON-data. Så här kommer koden att se ut:
geoJson()
Den nya koden är alltså den där vi skapar ett geoLayer
. Detta kommer att bli ett lager som ligger ovanpå vår karta och som visar information som läses utifrån vår GeoJSON-data. Lagret skapas av metoden L.geoJson()
. Vi ska titta närmare på hur denna fungerar.
Som första inparameter tar geoJson
-metoden antingen en enda post formaterad i GeoJSON eller en array med flera poster. I vårt fall har vi en array med GeoJSON-data, så vi skickar med den, dvs geoData.features
.
Som andra parameter skickar man med en lista som innehåller de stilparametrar som ska gälla för vår GeoJSON-data. Detta kan vara en lista med egenskaper som används för all data. Det kan även vara ett objekt som innehåller metoder som körs för att sätta specifik data för varje GeoJSON-objekt. I vårt fall har vi valt att skicka med metoder. Vi skulle även kunna lägga till stildata i objektet om vi ville det. Vi har valt att koppla en funktion till onEachFeature
. Denna funktion kommer att köras en gång för varje punkt som ingår i vår data.
onEachFeature
Den funktion vi skickar till onEachFeature
tar två inparametrar. Den första är nuvarande geografiska data som behandlas. I vårt fall är det en intressepunkt. Den andra parametern anger vilket lager som denna "feature" ska läggas till i. I vårt fall binder vi en popup till varje datapunkt, popup-texten kommer att vara namnet på intressepunkten.
Svårare än så är det inte att lägga in data som är formaterad i GeoJSON!
Att läsa in data från en datakälla
Nu när vår utritning fungerar är det dags att börja hämta data på "riktigt". Det kommer vi att göra genom att använda oss av AJAX. Om du behöver uppfriska dina kunskaper i AJAX, titta på aktiviteten "jQuery och AJAX". Vi plockar bort vår testdata och lägger till en funktion som hämtar data. Så här blir det att se ut:
Det som är nytt är främst hämtaIPLista
. Denna kommer att läsa ut en lista som innehåller Örebros badplatser. När datan är hämtad kommer funktionen AjaxKlar
att köras. Som inparameter får denna den data som lästs in. Denna data kan vi skicka in direkt i geoJson
, då den är precis lik den testdata som vi använde tidigare. Det är inget nytt i hur denna bit hanteras, koden är bara flyttad till en annan plats i programfilen.
Appen på riktigt
Om du vill se hur man skulle lagt upp appen på riktigt, det vill säga som fristående webbapplikation och inte som demo i Codepen, kan du gå till http://exempel.webbling.se/Leaflet.
Skillnaderna är att vi delat upp app:en i tre filer. En för HTML, en för CSS och en för JavaScript.
I HTML är skillnaden att det är med "grundstruktur" för sidan, sånt som inte behövs på Codepen. Det är även tillagt så att övriga app-delar laddas in. I CSS är inget ändrat.
JavaScript-delen har hamnat i app.js
. Vår app-kod har inkapslats i en funktion. Denna funktion körs igång när allt är inladdat. Detta gör vi för att vara säkra på att alla metoder vi kommer att anropa är nedladdade och tillgängliga.
Avslutning
Nu har du en liten SPA som visar upp karta och data. Om du klickar på en intressepunkt i kartan bör du få upp en popup som talar om namnet på badplatsen . Återigen, det är inte alltför mycket kod som behövs för att hämta data dynamiskt och visa upp denna på en fullt användbar karta.
Vi skulle lätt kunna ändra till att läsa in andra intressepunkter eller varför inte låta användaren välja vilka intressepunkter denne vill se? Det lämnar vi dock som en övning till läsare. Vi ska gå vidare och titta på hur man skapar applikationer som har en serverkomponent. Vi kommer att behöva detta för att kunna hämta vissa typer av data, t.ex. kräver många öppna data-källor att man har en API-nyckel för att kunna köra dem. Denna nyckel ska hållas hemlig, vilket är svårt eller omöjligt att göra om du kör en renodlad klientapp.
Nästa aktivitet
Vi ska gå igenom hur man skapar en till liten SPA.