Ghidul simplu al hărților Angular Leaflet

Leaflet este unul dintre principalele cadre de cartografiere bazate pe Javascript. Este utilizat pe scară largă în întreaga industrie pentru a adăuga hărți interactive la site-urile și aplicațiile web.

Cu toate acestea, poate fi dificil de inclus în aplicațiile Angular.io. Nu se potrivește tocmai bine nici cu Angular, nici cu Typescript. După ce am avut aventura de a migra un site bazat pe hărți Leaflet la Angular 8, mi-a fost clar că nu există o referință cu adevărat bună pentru această sarcină. Aceste postări sunt încercarea mea de a documenta învățăturile. (UPDATE: Deși acest articol a fost scris pentru Angular 8 – aplicațiile și metodele funcționează în continuare în Angular 11).

Aceasta va fi o postare în mai multe părți :

  • Elemente de bază (acest post),
  • Adăugarea de controale,
  • Funcții & Controale dinamice,
  • Controale personalizate, și
  • Văzând PWA – service workers și multe altele

Obiectivul acestei serii este ca voi să puteți crea o hartă Leaflet într-un proiect bazat pe Angular-CLI fără bătăi de cap, agitație și fundături.

Se pare că, deși adăugarea Leaflet la Angular.io nu este semnificativ de dificilă, este foarte „fiddly”, deoarece Leaflet nu este deosebit de prietenos cu Angular (sau Typescript). Leaflet folosește o structură de variabile globale L și .extend metode care încurcă TS. De asemenea, procesează un volum de evenimente care ar îngenunchea aplicațiile Angular dacă ar fi trecute prin detectarea modificărilor.

Din fericire, există un punct de plecare bun în @asymmetrik/ngx-leaflet. Acesta oferă o configurație destul de mult boilerplate pentru hărți de bază. vine, de asemenea, cu câteva tutoriale bune pentru hărți de bază (aici și aici), dar se pare că și-au pierdut interesul înainte de a ajunge la lucrurile dificile.

Getting Started

Conform documentației, trebuie să instalați :

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

și să adăugați importurile în app.module.ts.

În acest punct – puteți cam adăuga o hartă simplă la aplicație, așa că s-ar putea să vă gândiți de ce a fost atâta agitație – dar vom ajunge la asta.

Complicații CSS

În primul rând, trebuie să vorbim despre CSS. Ngx-leaflet rulează Leaflet în afara lui Angular însuși – ceea ce înțeleg că este cel mai bun mod de a evita ca evenimentele Leaflet să provoace mai multe evenimente de schimbare în Angular.

Dar, probabil din această cauză, Leaflet nu se încadrează în sistemul de încapsulare CSS de la Angular.io și toate referințele CSS trebuie să fie la nivel global.

Acest lucru înseamnă, de obicei, că adăugați CSS-ul Leaflet în angular.json după cum urmează

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

sau în styles.css:

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

Acest lucru este valabil și pentru foile de stil pentru fiecare control, ceea ce devine obositor deoarece, în Leaflet, fiecare control are propriul CSS. Am constatat că cel mai bun lucru a fost să adaug CSS-ul Leaflet la angular.json și CSS-ul fiecărui control în parte la styles.css, în primul rând pentru o mai bună lizibilitate.

Rețineți că, în ambele cazuri, leaflet.css ar trebui să fie procesat înaintea celorlalte CSS din styles.css. În caz contrar, CSS-ul pentru controale nu va fi eficient.

Complicații ale compilatorului

Acesta este, de asemenea, locul în care începem să întâlnim una dintre primele complicații ale compilatorului.

Aplicațiile bazate pe leaflet create în acest fel funcționează pentru ng build și funcționează cu "aot": true dar par să eșueze grav pentru configurația implicităng build --prod.

Acest lucru pare să fie în jurul optimizării și cred că poate se reduce la tree-shaking. După câteva experimente, am descoperit că ng build --prod funcționează în mod fiabil atâta timp cât "buildOptimizer": false este în angular.json.

Don’t Get Caught in L

Majoritatea tutorialelor și documentației vă vor spune că trebuie să aduceți variabila globală L în typescript folosind următorul import :

import * as L from 'leaflet'

Acest lucru este adevărat dacă doriți să folosiți codul JS existent direct în TS, dar am descoperit că, atâta timp cât ați încărcat @types/leaflet, puteți importa typedefs după nume din 'leaflet' (de ex.g) import {Map} from 'leaflet' și totul funcționează conform așteptărilor. Acest lucru face codul dvs. TS mult mai ușor de citit și, ei bine, TS-ish!

O hartă simplă

Așa că. Să creăm harta noastră. În exemplul de mai jos, creez o hartă OpenStreetMap (deoarece pe aceasta funcționează aplicația mea) ca o componentă separată. La acest nivel, acest lucru poate părea o muncă suplimentară, dar, vom vedea mai târziu, ne permite să configurăm o componentă de hartă cu caracteristici suplimentare care pot fi reutilizate în mai multe locuri din fluxul aplicației.

Această componentă setează în mod implicit un strat OSM și o vizualizare globală în opțiuni – deși opțiunile sunt configurate ca @Inputs(), astfel încât valorile implicite pot fi anulate de către componenta părinte.

Componenta hartă emite, de asemenea, evenimente atunci când harta este gata, astfel încât alte părți ale aplicației să poată accesa harta, și după un eveniment de zoom cu noul nivel de zoom. De asemenea, puteți emite și alte evenimente, cum ar fi evenimentele de mutare și de strat – dar de acest lucru avea nevoie aplicația mea și cred că demonstrează principiul. Vom folosi evenimentele de hartă și de zoom în următoarele secțiuni.

Harta este adăugată la dom folosind directiva ngx-leaflet în HTML-ul componentei.

În cele din urmă, componenta este utilizată prin adăugarea următoarelor la HTML-ul părinte:

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

Read This Next