# Leaflet

## Vad det är

Leaflet är ett JavaScript-bibliotek med öppen källkod som gör ett element på en webbsida till en
karta som går att panorera, zooma och klicka i. Projektet anger storleken till ungefär 42 KB
JavaScript och listar inga externa beroenden. Det skapades av Volodymyr Agafonkin, utvecklas i dag
av en gemenskap av bidragsgivare och ges ut under licensen BSD 2-Clause.

Projektets egen översikt säger att det inte försöker göra allt för alla, utan koncentrerar sig på
att få grunderna att fungera väl. `L.map` tar ett element och en uppsättning alternativ och blir
kartan. Ett lager med kartplattor (tiles) hämtar kvadratiska bilder från en URL-mall med `{z}`,
`{x}` och `{y}` i sig och lägger ut dem som ett rutnät av bildelement, och en WMS-variant gör samma
sak mot en Web Map Service. Linjer, polygoner, cirklar och rektanglar ritas som SVG som standard,
eller på en enda canvas när kartan skapas med `preferCanvas`. Markörer är ikoner, antingen en bild
eller en enkel `div`, med popup-rutor och verktygstips kopplade till sig. Ett GeoJSON-lager gör
varje objekt till ett av de lagren, en punkt till en markör om inget annat anges. Zoomknappar,
källhänvisning, en lagerväljare och en skalstock utgör kontrollerna. Standardsystemet för
koordinater är EPSG:3857, som referensdokumentationen kallar det vanligaste för kartor på nätet.

Allt utöver den listan kommer från tillägg. Projektets databas över tillägg beskriver Leaflet som
tänkt att vara så lätt som möjligt och pekar på hundratals tillägg från tredje part, sorterade i
grupper som vektorplattor, klustring, värmekartor, redigering av geometri, ruttplanering och
geokodning.

Två utgivningslinjer finns när detta skrivs. Den stabila är 1.9.4, utgiven den 18 maj 2023, och
API-referensen på projektets webbplats motsvarar den. Förhandsversionen, 2.0.0-alpha.1 från den
16 augusti 2025, tar bort stödet för Internet Explorer och levereras som en ES-modul. Den behåller
det globala `L` bara i en paketerad `leaflet-global.js`, ersätter fabriksfunktioner med
konstruktorer, så att `L.marker(latlng)` blir `new Marker(latlng)`, och tar emot inmatning via
pekarhändelser (pointer events).

## Varför det spelar roll

Att sätta en karta på en sida är två beslut som är lätta att ta för ett: vilken kod som ritar kartan
i webbläsaren, och varifrån kartbilderna kommer. Leaflet håller isär dem, och valet att använda det
är till stor del ett val att hålla isär dem.

Leaflet ritar. Kartplattorna kommer från dit URL-mallen pekar, så bakgrundskartan är ett separat
beslut med eget pris, egna villkor och egen ägare. Den kan vara OpenStreetMaps server för
kartplattor medan en funktion byggs, en kommersiell leverantör i produktion, en server som
projektet driver själv eller en kommuns WMS via `TileLayer.WMS`. Att byta mellan dem ändrar en
sträng och en rad med källhänvisning, och applikationskoden runt kartan förblir som den är.

Storleken och licensen avgör var Leaflet passar bra. Ungefär 42 KB och inga beroenden passar en
sida där kartan är en del bland många: ett formulär där någon sätter ut en nål, eller en
administrationsvy som visar var poster finns. Licensen BSD 2-Clause lägger inget konto, ingen
nyckel och ingen mätning av användningen mellan biblioteket och sidan.

Priset för en liten kärna är att tyngre funktioner kommer som separata paket, vart och ett med egen
underhållare och egen utgivningstakt, och en karta som lutar sig mot sex tillägg ärver sex
uppgraderingsvägar. Alfan av 2.0 visar vad det betyder: dess migreringsanvisningar hänvisar den som
använder äldre tillägg till en polyfill för V1, eftersom de tilläggen förväntar sig det globala `L`
och fabriksfunktionerna. En karta som behöver vektorplattor som stilsätts i webbläsaren på varje
zoomnivå passar bättre i ett bibliotek som är byggt kring dem, och det beslutet fattas helst innan
sex tillägg håller uppe kartan.

## Så ser det ut i praktiken

Leaflet förekommer på två sidor på den här webbplatsen, båda från rollen som teamledare för
utveckling av GIS-mjukvara mellan 2015 och 2022, och på båda delar det frontenden med Mapbox.

Rollen hade ansvar för
[mer än trettio GIS-projekt](/sv/portfolio/led-the-development-deployment-and-support-of-over-35/)
genom utveckling och driftsättning. Det projekten visade utåt var webbkartor byggda på Leaflet och
Mapbox GL, ibland kopplade mot ArcGIS- eller HERE-API:erna, och koden runt kartorna skrevs i
JavaScript, Python, PHP och SQL. Under låg PostgreSQL med PostGIS, och GDAL/OGR flyttade data mellan
shapefiler, GeoJSON, GeoTIFF, KML och vektorplattor. Ansvaret sträckte sig längre än till
leveransen, ända in i supporten i produktion.

Samma roll fanns också med i
[designprocessen för projektens användargränssnitt](/sv/portfolio/contributed-to-user-interface-design-processes-ensuring-intuitive-36/).
Det var frontends i React, Angular och Vue ovanpå kartor i Mapbox och Leaflet, och sidan gör en
poäng som är värd att ha bredvid vilket kartbibliotek som helst: i en webbkartprodukt är kartan den
enkla delen, och det är i kontrollerna, filtreringen och flödet runt den som folk går vilse.
Användbarheten satt i detaljer som hur en datamängd filtrerades och hur man rörde sig mellan
våningsplan på en inomhuskarta, och sidan tillskriver det mesta av skillnaden att de frågorna
ställdes under designen och inte efter lanseringen.

## Var det går fel

Leaflet är så litet att de flesta av dess fel kommer från sidan runt det, eller från de tjänster
det pekas mot.

**Kartan visas som en grå ruta eller en remsa av lösa kartplattor.** Leaflet tar sin storlek från
sin behållare. Snabbstartsguiden listar två saker att göra innan någon kartkod körs: ladda Leaflets
CSS-fil före JavaScript-koden, och ge behållaren en bestämd höjd. En `div` utan höjd ger en karta
utan höjd. Ett lurigare fall är en karta som skapas inuti en flik eller en dialog som är dold just
då: den mäter sig själv till noll och behåller den storleken när den visas. Leaflet 1.x följer när
webbläsarfönstret ändrar storlek, via `trackResize`, så en behållare som ändrar storlek av sig själv
passerar obemärkt tills koden anropar `invalidateSize()`, som referensen säger ska anropas när
kartans storlek har ändrats. Alfan av 2.0 använder `ResizeObserver` i stället för fönstrets
resize-händelse.

**Punkter hamnar tusentals kilometer bort.** GeoJSON, så som RFC 7946 definierar det, skriver en
position med longituden först. Leaflets `LatLng` och de arrayer som det tar emot i stället har
latituden först. `L.geoJSON` översätter mellan de två på egen hand, så buggen dyker upp när
koordinater plockas ut ur GeoJSON för hand och skickas direkt till en markör eller en linje. En
punkt i Stockholm hamnar, omkastad, i Arabiska havet. Packa upp paret med namn vid gränsen:

```js
const res = await fetch("/api/sites/42");
const site = await res.json();
const [lon, lat] = site.geometry.coordinates; // GeoJSON: lon, lat
L.marker([lat, lon]).addTo(map); // Leaflet: lat, lng
```

**Panoreringen hackar när datan växer.** Med SVG-renderaren är varje linje eller polygon ett eget
element i dokumentet, och varje standardmarkör en egen bild. Ett lager med många tusen objekt
betyder många tusen element som webbläsaren måste flytta vid varje panorering och zoomning.
Alternativet `preferCanvas: true` ritar banor på en enda canvas, men gäller bara banor, så punkter
måste bli `L.circleMarker`, en cirkel med fast radie i pixlar som själv är en bana, via
GeoJSON-lagrets alternativ `pointToLayer`. Bortom den gränsen är svaret att skicka mindre: ett
tillägg för klustring, eller ett API som bara returnerar det som får plats i den aktuella vyn och
zoomnivån.

**Kartplattorna slutar laddas efter lanseringen.** Snabbstartsguiden bygger sin första karta på
OpenStreetMaps server för kartplattor och säger rakt ut att de plattorna går bra under
programmering, men att användningsvillkoren, Tile Usage Policy, ska läsas före produktion.
Villkoren ber om synlig källhänvisning, en User-Agent som identifierar applikationen och en giltig
Referer från webbsidor, cachning enligt HTTP-huvudena och att ingen massnedladdning eller
förhämtning görs. De erbjuder inget servicenivåavtal, och åtkomsten kan spärras utan förvarning. En
välbesökt karta i produktion hör hemma hos en leverantör vars villkor passar trafiken, eller på en
egen server för kartplattor, och med Leaflet består flytten av URL-mallen och källhänvisningen.

## Läs mer

- [Leaflet](https://leafletjs.com/) — projektets översikt, funktionslista och en första karta på
  några få rader.
- [Leaflet API reference](https://leafletjs.com/reference.html) — varje klass, alternativ och
  metod i 1.9.4, bl.a. `preferCanvas`, `invalidateSize` och alternativen för GeoJSON.
- [Leaflet Quick Start Guide](https://leafletjs.com/examples/quick-start/) — CSS-filen,
  behållarens höjd och ett första lager med kartplattor, steg för steg.
- [Leaflet 2.0 Alpha released](https://leafletjs.com/2025/05/18/leaflet-2.0.0-alpha.html)
  — vad som ändras i 2.0 och hur kod och tillägg migreras.
- [Tile Usage Policy](https://operations.osmfoundation.org/policies/tiles/) — villkoren för att
  använda kartplattorna från openstreetmap.org.
- [RFC 7946: The GeoJSON Format](https://www.rfc-editor.org/rfc/rfc7946) — GeoJSON-standarden,
  inklusive ordningen med longituden först i positioner.

<https://engineer.company/sv/glossary/leaflet/>
