Yksinkertainen opas Angularin Leaflet-karttoihin

Leaflet on yksi tärkeimmistä Javascript-pohjaisista karttakehyksistä. Sitä käytetään laajalti eri puolilla teollisuutta interaktiivisten karttojen lisäämiseen verkkosivuille ja -sovelluksiin.

Mutta sen sisällyttäminen Angular.io-sovelluksiin voi olla hankalaa. Se ei oikein sovi yhteen Angularin tai Typescriptin kanssa. Seikkailtuani siirtäessäni Leaflet-karttapohjaisen sivuston Angular 8:aan minulle oli selvää, että tähän tehtävään ei ollut oikein hyvää referenssiä. Nämä viestit ovat yritykseni dokumentoida opit. (PÄIVITYS: Vaikka tämä artikkeli on kirjoitettu Angular 8:lle – sovellukset ja menetelmät toimivat edelleen Angular 11:ssä).

Tästä tulee moniosainen postaus :

  • Perusteet (tämä viesti),
  • Ohjainten lisääminen,
  • Funktiot & Dynaamiset ohjaimet,
  • Mukautetut ohjaimet, ja
  • Going PWA – service workers and more

Tämän sarjan tavoitteena on, että pystyt luomaan Leaflet-kartan Angular-CLI-pohjaiseen projektiin ilman vaivaa, hässäkkää ja umpikujia.

Kävi ilmi, että vaikka Leafletin lisääminen Angular.ioon ei ole merkittävästi vaikeaa, se on hyvin ”hankalaa”, koska Leaflet ei ole erityisen Angular (tai Typescript) -ystävällinen. Leaflet käyttää globaalia Lmuuttujarakennetta ja .extend metodeja, jotka hämmentävät TS:ää. Se myös käsittelee niin paljon tapahtumia, että Angular-sovellukset polvistuisivat, jos ne laitettaisiin muutostunnistuksen läpi.

Onneksi @asymmetrik/ngx-leaflet:ssa on hyvä lähtökohta. Tämä tarjoaa aika lailla boilerplate-asetukset peruskartoille. sen mukana tulee myös pari hyvää tutoriaalia peruskartoitukseen (täällä ja täällä), mutta ne näyttävät menettäneen mielenkiintonsa ennen kuin pääsivät vaikeisiin asioihin.

Alkuun pääseminen

Dokumentaation mukaan sinun täytyy asentaa :

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

ja lisätä importit app.module.ts.

Tässä vaiheessa – voit melko hyvin lisätä yksinkertaisen kartan sovellukseen, joten saatat miettiä, mistä tämä hössötys johtui – mutta siihen tulemme vielä.

CSS-komplikaatiot

Ensin on puhuttava CSS:stä. Ngx-leaflet ajaa Leafletia itse Angularin ulkopuolella – mikä käsittääkseni on paras tapa välttää se, että Leaflet-tapahtumat aiheuttavat useita muutostapahtumia Angularissa.

Mutta luultavasti tästä johtuen Leaflet ei sovi Angular.io:n CSS-kapselointijärjestelmään ja kaikkien CSS-viittausten on oltava globaalilla tasolla.

Tämä tarkoittaa yleensä sitä, että Leafletin CSS lisätään angular.json-tiedostoon seuraavasti

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

tai styles.css-tiedostoon:

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

Tämä pätee myös jokaisen ohjaimen tyylitiedostoihin, mikä käy rasittavaksi, koska Leafletissa jokaisella ohjaimella on oma CSS. Huomasin parhaaksi lisätä Leafletin CSS:n kohtaan angular.json ja yksittäisen ohjaimen CSS:n kohtaan styles.css lähinnä paremman luettavuuden vuoksi.

Huomaa, että kummassakin tapauksessa leaflet.css tulee käsitellä ennen muuta CSS:ää styles.css:ssä. Muuten ohjainten CSS ei ole tehokas.

Kääntäjän komplikaatiot

Tässä kohtaa alamme myös törmätä yhteen ensimmäisistä kääntäjän komplikaatioista.

Tällaiset näin luodut leaflet-pohjaiset sovellukset toimivat ng build:llä ja toimivat "aot": true :llä, mutta näyttävät epäonnistuvan pahasti oletusarvoisen ng build --prod-konfiguraation kohdalla.

Tämä näyttäisi olevan optimoinnin ympärillä, ja luulen, että ehkä puun ravistelun takia. Joidenkin kokeilujen jälkeen huomasin, että ng build --prod toimii luotettavasti niin kauan kuin "buildOptimizer": false on angular.json:ssä.

Ei saa jäädä kiinni L:stä

Suurimmassa osassa opetusohjelmia ja dokumentaatiota kerrotaan, että globaali L-muuttuja on tuotava typescriptiin seuraavalla importilla :

import * as L from 'leaflet'

Tämä pitää paikkansa, jos haluaa käyttää olemassaolevaa JS-koodia suoraan TS:ssä, mutta huomasin, että niin kauan kuin lataat @types/leaflet, voit tuoda typedefejä nimeltä 'leaflet':stä (esim.esim. import {Map} from 'leaflet' ja kaikki toimii odotetusti. Tämä tekee TS-koodistasi paljon luettavampaa ja, noh, TS-mäisempää!

A Simple Map

So. Luodaanpa meidän karttamme. Alla olevassa esimerkissä luon OpenStreetMap-kartan (koska sovellukseni toimii sillä) erillisenä komponenttina. Tällä tasolla tämä voi tuntua ylimääräiseltä työltä, mutta näemme myöhemmin, että sen avulla voimme luoda karttakomponentin, jossa on lisäominaisuuksia, joita voidaan käyttää uudelleen useissa paikoissa sovelluksen virtauksessa.

Tämä komponentti käyttää oletusarvoisesti OSM-tasoa ja globaalia näkymää asetuksissa – tosin asetukset on määritetty @Inputs():ksi, joten emokomponentti voi ohittaa oletusarvot.

Karttakomponentti lähettää myös tapahtumia, kun kartta on valmis, jotta sovelluksen muut osat pääsevät käsiksi karttaan, ja sen jälkeen zoomaustapahtuman uudella zoomaustasolla. Voit lähettää myös muita tapahtumia, kuten siirto- ja tasotapahtumia – mutta tätä sovellukseni tarvitsi ja mielestäni se havainnollistaa periaatteen. Käytämme kartta- ja zoomaustapahtumia seuraavissa osioissa.

Kartta lisätään domiin ngx-leaflet-direktiivin avulla komponentin HTML:ssä.

Viimeiseksi komponenttia käytetään lisäämällä vanhemman HTML:ään seuraava:

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

Lue tämä seuraavaksi