De eenvoudige gids voor Angular Leaflet Maps

Leaflet is een van de belangrijkste Javascript-gebaseerde mapping frameworks. Het wordt veel gebruikt in de industrie om interactieve kaarten toe te voegen aan websites en applicaties.

Het kan echter lastig zijn om op te nemen in Angular.io apps. Het speelt niet echt mooi met ofwel Angular of Typescript. Nadat ik het avontuur had van het migreren van een Leaflet map-gebaseerde site naar Angular 8 was het duidelijk voor mij dat er geen echt goede referentie was voor deze taak. Deze posts zijn mijn poging om het geleerde te documenteren. (UPDATE: Hoewel dit artikel is geschreven voor Angular 8 – de toepassingen en methoden werken nog steeds in Angular 11).

Dit wordt een post in meerdere delen :

  • De basis (deze post),
  • Controls toevoegen,
  • Functies & Dynamische Controls,
  • Aangepaste Controls, en
  • Ga naar PWA – service workers en meer

Het doel van deze serie is dat je in staat zult zijn om een Leaflet map te maken in een Angular-CLI gebaseerd project zonder gedoe, ophef en doodlopende wegen.

Het blijkt dat, hoewel het toevoegen van Leaflet aan Angular.io niet noemenswaardig moeilijk is, het wel erg “prutswerk” is omdat Leaflet niet bijzonder Angular (of Typescript) vriendelijk is. Leaflet gebruikt een globale L variabele structuur en .extend methodes die TS in verwarring brengen. Het verwerkt ook een hoeveelheid events die Angular apps op de knieën zouden krijgen als ze door change detection zouden worden gehaald.

Gelukkig is er een goed startpunt in @asymmetrik/ngx-leaflet. Dit biedt een vrij veel boilerplate setup voor basis mapping. het komt ook met een paar goede tutorials om basis mapping (hier en hier), maar ze lijken te hebben verloren interesse voordat ze naar de harde stuff.

Getting Started

Volgens de documentatie, moet u installeren :

npm install leaflet
npm install @types/leaflet
npm install @asymmetrik/ngx-leaflet

en voeg de invoer aan de app.module.ts.

Op dit punt – je kunt vrij veel een eenvoudige kaart toe te voegen aan de app, dus je zou kunnen denken waar de ophef over was – maar we komen naar dat.

CSS Complicaties

Eerst moeten we het hebben over CSS. Ngx-leaflet draait Leaflet buiten Angular zelf – wat naar ik begrijp de beste manier is om te voorkomen dat Leaflet events meerdere change events in Angular veroorzaken.

Maar, waarschijnlijk hierdoor, past Leaflet niet in het Angular.io CSS inkapseling systeem en moeten alle CSS referenties op globaal niveau zijn.

Dit betekent meestal dat je de Leaflet CSS in angular.json als volgt toevoegt

{
...
"styles": ,
...
}

of in styles.css:

@import "./node_modules/leaflet/dist/leaflet.css"

Dit geldt ook voor de stylesheets voor elk control, wat vermoeiend wordt omdat in Leaflet elk control zijn eigen CSS heeft. Ik vond het het beste om de Leaflet CSS toe te voegen aan angular.json en de individuele controle CSS aan styles.css, voornamelijk voor een betere leesbaarheid.

Noteer dat, in beide gevallen, de leaflet.css moet worden verwerkt vóór de andere CSS in styles.css. Anders zal de CSS voor de controls niet effectief zijn.

Compiler Complicaties

Dit is ook waar we een van de eerste compiler complicaties tegenkomen.

Leaflet gebaseerde apps die op deze manier zijn gemaakt werken voor ng build en werken met "aot": true , maar lijken slecht te falen voor de standaardng build --prod configuratie.

Dit lijkt te maken te hebben met optimalisatie en ik denk dat het misschien te maken heeft met tree-shaking. Na wat experimenteren, vond ik dat ng build --prod betrouwbaar werkt zolang "buildOptimizer": false in angular.json staat.

Don’t Get Caught in L

De meeste tutorials en documentatie zullen u vertellen dat u de globale L variabele in typescript moet brengen met de volgende import :

import * as L from 'leaflet'

Dit is waar als u bestaande JS code direct in de TS wilt gebruiken, maar ik ontdekte dat zolang u @types/leaflet laadde, u de typedefs op naam kunt importeren uit 'leaflet' (bijv.bijv. import {Map} from 'leaflet' en het werkt allemaal zoals verwacht. Dit maakt uw TS code veel leesbaarder en, nou ja, TS-achtig!

Een eenvoudige kaart

Zo. Laten we onze kaart maken. In het voorbeeld hieronder maak ik een OpenStreetMap kaart (omdat dat is waar mijn app op werkt) als een apart component. Op dit niveau lijkt dit misschien extra werk, maar we zullen later zien dat het ons in staat stelt een kaart component op te zetten met extra functies die op meerdere plaatsen in de app flow hergebruikt kunnen worden.

Deze component is standaard ingesteld op een OSM-laag en een globale weergave in de opties – hoewel de opties zijn ingesteld als @Inputs(), zodat de standaardwaarden kunnen worden overschreven door de bovenliggende component.

De kaart component zendt ook gebeurtenissen uit wanneer de kaart klaar is, zodat andere delen van de app toegang hebben tot de kaart, en na een zoom gebeurtenis met het nieuwe zoomniveau. Je kunt ook andere events uitzenden, zoals move en layer events – maar dit is wat mijn app nodig had en ik denk dat het het principe demonstreert. We zullen de kaart- en zoom-events in de volgende secties gebruiken.

De kaart wordt aan de dom toegevoegd met behulp van de ngx-leaflet-richtlijn in de component-HTML.

Ten slotte wordt de component gebruikt door het volgende aan de parent HTML toe te voegen:

<app-osm-map
="options"
(map$)="receiveMap($event)"
(zoom$)="receiveZoom($event)"
></app-osm-map>

Lees dit verder