Prosty przewodnik po Angular Leaflet Maps

Leaflet jest jednym z głównych frameworków mapowania opartych na Javascript. Jest on szeroko stosowany w przemyśle do dodawania interaktywnych map do stron internetowych i aplikacji.

Jednakże, może on być trudny do włączenia do aplikacji Angular.io. Nie jest to dokładnie grać ładnie z Angular lub Typescript. Po tym, jak miałem przygodę z migracją witryny opartej na mapie Leaflet do Angular 8, stało się dla mnie jasne, że nie było naprawdę dobrego odniesienia do tego zadania. Te posty są moją próbą udokumentowania nauki. (UPDATE: Chociaż ten artykuł został napisany dla Angular 8 – aplikacje i metody nadal działają w Angular 11).

To będzie wieloczęściowy post :

  • Podstawy (ten post),
  • Dodawanie kontrolek,
  • Funkcje & Dynamiczne kontrolki,
  • Niestandardowe kontrolki, and
  • Going PWA – service workers and more

Celem tej serii jest to, że będziesz w stanie stworzyć mapę Leaflet w projekcie opartym na Angular-CLI bez kłopotów, zamieszania i ślepych zaułków.

Okazuje się, że chociaż dodanie Leaflet do Angular.io nie jest znacząco trudne, jest bardzo „kłopotliwe”, ponieważ Leaflet nie jest szczególnie przyjazny Angularowi (lub Typescriptowi). Leaflet używa globalnej L struktury zmiennych i .extend metod, które mylą TS. Przetwarza również ilość zdarzeń, które rzuciłyby aplikacje Angular na kolana, gdyby zostały poddane wykrywaniu zmian.

Na szczęście istnieje dobry punkt wyjścia w @asymmetrik/ngx-leaflet. To zapewnia dość dużo boilerplate setup dla podstawowych map. to również pochodzi z kilkoma dobrymi tutorialami do podstawowego mapowania (tutaj i tutaj), ale wydaje się, że stracili zainteresowanie, zanim dotarli do trudnych rzeczy.

Getting Started

Jak w dokumentacji, musisz zainstalować :

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

i dodać import do app.module.ts.

W tym momencie – możesz całkiem sporo dodać do aplikacji prostej mapy, więc możesz pomyśleć o co tyle zamieszania – ale dochodzimy do tego.

Komplikacje z CSS

Po pierwsze, musimy porozmawiać o CSS. Ngx-leaflet uruchamia leaflet poza samym Angularem – co, jak rozumiem, jest najlepszym sposobem na uniknięcie zdarzeń Leaflet powodujących wiele zdarzeń zmian w Angular.

Jednakże, prawdopodobnie z tego powodu, Leaflet nie pasuje do systemu enkapsulacji CSS Angular.io, a wszystkie odniesienia CSS muszą być na poziomie globalnym.

Zazwyczaj oznacza to, że dodajesz Leaflet CSS w angular.json w następujący sposób

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

lub w styles.css:

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

Odnosi się to również do arkuszy stylów dla każdej kontrolki, co staje się uciążliwe, ponieważ w Leaflet każda kontrolka ma swój własny CSS. Stwierdziłem, że najlepszą rzeczą będzie dodanie CSS dla Leaflet do angular.json a CSS dla poszczególnych kontrolek do styles.css głównie dla lepszej czytelności.

Zauważ, że w obu przypadkach, leaflet.css powinien być przetwarzany przed innymi CSS w styles.css. W przeciwnym razie, CSS dla kontrolek nie będzie efektywny.

Komplikacje kompilatora

To jest również miejsce, gdzie zaczynamy natrafiać na jedną z pierwszych komplikacji kompilatora.

Aplikacje oparte na leaflet stworzone w ten sposób działają dla ng build i działają z "aot": true , ale wydają się źle działać dla domyślnej konfiguracjing build --prod.

Wydaje się to być związane z optymalizacją i myślę, że może z trzęsieniem drzewa. Po pewnych eksperymentach stwierdziłem, że ng build --prod działa niezawodnie tak długo, jak "buildOptimizer": false jest w angular.json.

Don’t Get Caught in L

Większość tutoriali i dokumentacji powie ci, że musisz wprowadzić zmienną globalną L do typescript za pomocą następującego importu :

import * as L from 'leaflet'

To prawda, jeśli chcesz użyć istniejącego kodu JS bezpośrednio w TS, ale odkryłem, że tak długo, jak załadowałeś @types/leaflet, możesz zaimportować typedefs przez nazwę z 'leaflet' (np.np. import {Map} from 'leaflet' i wszystko działa zgodnie z oczekiwaniami. To czyni twój kod TS dużo bardziej czytelnym i, cóż, TS-owym!

Prosta mapa

Więc. Stwórzmy naszą mapę. W poniższym przykładzie, tworzę mapę OpenStreetMap (ponieważ na tym właśnie działa moja aplikacja) jako osobny komponent. Na tym poziomie, może się to wydawać dodatkową pracą, ale zobaczymy później, pozwala nam to na utworzenie komponentu mapy z dodatkowymi funkcjami, które mogą być ponownie wykorzystane w wielu miejscach w przepływie aplikacji.

Komponent ten domyślnie ustawia warstwę OSM i widok globalny w opcjach – chociaż opcje są ustawione jako @Inputs(), więc wartości domyślne mogą być nadpisane przez komponent nadrzędny.

Komponent mapy emituje również zdarzenia, gdy mapa jest gotowa, aby inne części aplikacji mogły uzyskać dostęp do mapy, oraz po zdarzeniu zoomu z nowym poziomem zoomu. Możesz również emitować inne zdarzenia, takie jak zdarzenia przesunięcia i warstwy – ale to jest to, czego potrzebowała moja aplikacja i myślę, że to demonstruje zasadę. Będziemy używać zdarzeń mapy i zoomu w następnych sekcjach.

Mapa jest dodawana do domeny za pomocą dyrektywy ngx-leaflet w HTML komponentu.

Na koniec, komponent jest używany przez dodanie następujących elementów do HTML rodzica:

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

Read This Next

.