Le guide simple des cartes Angular Leaflet

Leaflet est l’un des principaux frameworks de cartographie basés sur Javascript. Il est largement utilisé à travers l’industrie pour ajouter des cartes interactives aux sites et applications web.

Cependant, il peut être délicat à inclure dans les applications Angular.io. Il ne joue pas exactement bien avec Angular ou Typescript. Après avoir eu l’aventure de migrer un site basé sur une carte Leaflet vers Angular 8, il était clair pour moi qu’il n’y avait pas vraiment de bonne référence pour cette tâche. Ces billets sont ma tentative de documenter les apprentissages. (MISE À JOUR : Bien que cet article ait été écrit pour Angular 8 – les applications et les méthodes fonctionnent toujours dans Angular 11).

Ce sera un post en plusieurs parties :

  • Les bases (ce post),
  • Ajout de contrôles,
  • Fonctions & Contrôles dynamiques,
  • Contrôles personnalisés, et
  • Voir PWA – travailleurs de service et plus

L’objectif de cette série est de que vous serez en mesure de créer une carte Leaflet dans un projet basé sur Angular-CLI sans tracas, agitation et impasses.

Il s’avère que, bien que l’ajout de Leaflet à Angular.io ne soit pas significativement difficile, il est très « bricolé » puisque Leaflet n’est pas particulièrement Angular (ou Typescript) friendly. Leaflet utilise une structure de variable globale L et des méthodes .extend qui déroutent TS. Il traite également un volume d’événements qui mettrait les applications Angular à genoux si elles étaient soumises à la détection des changements.

Heureusement, il existe un bon point de départ dans @asymmetrik/ngx-leaflet. Cela fournit une configuration à peu près boilerplate pour les cartes de base. il est également livré avec un couple de bons tutoriels à la cartographie de base (ici et ici), mais ils semblent vraiment avoir perdu l’intérêt avant d’arriver à la substance dure.

Getting Started

Selon la documentation, vous devez installer :

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

et ajouter les importations à la app.module.ts.

À ce stade – vous pouvez à peu près ajouter une carte simple à l’application, donc vous pourriez penser ce que l’agitation était au sujet – mais nous allons venir à cela.

CSS Complications

D’abord, nous devons parler de CSS. Ngx-leaflet exécute leaflet en dehors d’Angular lui-même – ce que je comprends comme étant la meilleure façon d’éviter que les événements Leaflet ne provoquent de multiples événements de changement dans Angular.

Cependant, probablement à cause de cela, Leaflet ne s’intègre pas dans le système d’encapsulation CSS d’Angular.io et toutes les références CSS doivent être au niveau global.

Cela signifie généralement que vous ajoutez la CSS de Leaflet dans angular.json comme suit

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

ou dans styles.css:

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

Cela vaut également pour les feuilles de style de chaque contrôle, ce qui devient lassant puisque, dans Leaflet, chaque contrôle a sa propre CSS. J’ai trouvé que la meilleure chose était d’ajouter le CSS de Leaflet à angular.json et le CSS de chaque contrôle à styles.css principalement pour une meilleure lisibilité.

Notez que, dans les deux cas, le leaflet.css doit être traité avant les autres CSS dans styles.css. Sinon, le CSS pour les contrôles ne sera pas efficace.

Complications du compilateur

C’est également là que nous commençons à rencontrer l’une des premières complications du compilateur.

Les applications basées sur leaflet créées comme cela fonctionnent pour ng build et fonctionnent avec "aot": true mais semblent échouer gravement pour la configuration par défautng build --prod.

Cela semble être autour de l’optimisation et je pense peut-être vers le bas pour le tree-shaking. Après quelques expérimentations, j’ai trouvé que ng build --prod fonctionne de manière fiable tant que "buildOptimizer": false est dans angular.json.

Ne vous faites pas prendre en L

La plupart des tutoriels et de la documentation vous diront que vous devez amener la variable globale L dans typescript en utilisant l’import suivant :

import * as L from 'leaflet'

C’est vrai si vous voulez utiliser le code JS existant directement dans le TS, mais j’ai trouvé que tant que vous avez chargé @types/leaflet, vous pouvez importer les typedefs par nom à partir de 'leaflet' (par ex.par exemple import {Map} from 'leaflet' et tout fonctionne comme prévu. Cela rend votre code TS beaucoup plus lisible et, bien, TS-ish!

A Simple Map

So. Créons notre carte. Dans l’exemple ci-dessous, je crée une carte OpenStreetMap (puisque c’est ce sur quoi mon application fonctionne) en tant que composant séparé. À ce niveau, cela peut sembler un travail supplémentaire, mais nous verrons plus tard, cela nous permet de mettre en place un composant de carte avec des fonctionnalités supplémentaires qui peuvent être réutilisées à plusieurs endroits dans le flux de l’app.

Ce composant utilise par défaut une couche OSM et une vue globale dans les options – bien que les options soient configurées comme @Inputs() afin que les valeurs par défaut puissent être remplacées par le composant parent.

Le composant de carte émet également des événements lorsque la carte est prête afin que d’autres parties de l’app puissent accéder à la carte, et après un événement de zoom avec le nouveau niveau de zoom. Vous pouvez également émettre d’autres événements tels que les événements de déplacement et de couche – mais c’est ce dont mon application avait besoin et je pense que cela démontre le principe. Nous utiliserons les événements de carte et de zoom dans les sections suivantes.

La carte est ajoutée au dom à l’aide de la directive ngx-leaflet dans le HTML du composant.

Enfin, le composant est utilisé en ajoutant ce qui suit au HTML parent:

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

Lisez cette suite

.