Integrazione di mappe nella tua applicazione Angular con Leaflet

Integrazione di mappe Leaflet nella versione Angular 8
Jim Armstrong
Jim Armstrong

Follow

Ott 17, 2019 – 6 min read

Questo articolo è orientato agli sviluppatori Angular principianti che desiderano integrare Leaflet nelle loro applicazioni. L’integrazione di dipendenze di terze parti in Angular può essere da banale a problematica. Mentre Leaflet tende più verso il lato banale, le mappe che si adattano fluidamente alle dimensioni del browser possono presentare alcuni problemi di configurazione relativi al ciclo di vita di Angular.

Prima di iniziare la decostruzione, puntate il vostro amichevole, vicino browser al seguente Github.

Ora, potete seguire il progetto o fare un fork e usarlo come base per le vostre applicazioni.

Sfondo

Questo tutorial presuppone una piccola quantità di conoscenza precedente di Leaflet, ma non più di quanto espresso nella Guida Rapida di Leaflet.

ArcGis è usato per il tiling nell’applicazione trattata in questo articolo (il pacchetto esri-leaflet è installato da npm).

Sistemazione angolare

Molto poco deve essere fatto dopo l’onnipresente installazione di npm. Gli stili Leaflet necessari sono resi disponibili attraverso il file angular.json,

"styles": ,

Ho avuto risultati contrastanti con @types/leaflet, quindi questa applicazione non sfrutta le tipologie per amore della semplicità. Leaflet e le piastrelle ESRI sono importate come mostrato qui sotto,

import * as esri from 'esri-leaflet';
import * as L from 'leaflet';

Una mappa Leaflet, per esempio, è temporaneamente digitata come qualsiasi; sentitevi liberi di consolidare le tipizzazioni come esercizio dopo aver decostruito il tutorial.

Le coordinate del centro di una mappa sono importanti per l’inizializzazione della mappa. Molti demo codificano queste informazioni. Come alternativa, questo tutorial illustra come iniettare le coordinate del centro della mappa usando i Token di iniezione di Angular.

Una coordinata è un punto bidimensionale su una mappa, rappresentato da latitudine e longitudine. Un InjectionToken per una coordinata può essere creato come illustrato nel file /src/app/tokens.ts,

import { InjectionToken } from '@angular/core';
export const INIT_COORDS = new InjectionToken<{lat: number, long: number}>('INIT_COORDS');

INIT_COORDS è usato nel file /src/app/app.module.ts per eseguire la disposizione (o definizione) effettiva (lat/long),

providers: ,

Questo sposta la definizione del centro della mappa al livello più alto nell’applicazione Angular (dove è facilmente visibile e quasi auto-documentata).

Per iniettare questa coordinata nell’applicazione, importa INIT_COORDS dal file tokens e inietta da un costruttore di classe. Questo è illustrato nel file /src/app/map.component.ts (il componente principale della mappa in questo tutorial),

constructor( @Inject(INIT_COORDS) protected _initCoords: {lat: number, long: number} )

Componente della mappa

L’applicazione trattata in questo articolo visualizza una mappa ad altezza fissa con una larghezza che si estende per tutta la finestra del browser. La mappa viene ridisegnata quando la finestra si ridimensiona. Alcuni marcatori sono anche resi sopra le piastrelle della mappa.

La mappa è integrata nell’applicazione attraverso il template del componente principale dell’app, come mostrato di seguito

/src/app/app.component.html

<app-map ="markers"></app-map>

e il codice sorgente del componente mappa si trova in /src/app/maps/map.component.ts .

La mappa viene resa in un contenitore (DIV) che si trova attualmente nel template del componente mappa,

/src/app/maps/map.component.html

<div>
<div>
<div #primaryMap ="currentHeight" ="currentWidth"></div>
<map-control class="map-control"></map-control>
<div class="mouse-coords">
<span></span>
<span ="mcText"></span>
</div>
</div>
</div>

Se la larghezza e l’altezza del DIV contenente sono fisse, allora le tiles della mappa possono essere rese in un punto iniziale del ciclo di vita del componente. Sono possibili due approcci per passare larghezza e altezza variabili, outside-in e inside-out. Il metodo outside-in definisce gli input Angular per la larghezza e l’altezza. Il componente padre è responsabile della comunicazione di larghezza e altezza al componente mappa. L’approccio inside-out definisce la larghezza e l’altezza internamente al componente della mappa e “passa” queste informazioni al suo template. La maggior parte delle applicazioni usa l’approccio outside-in. Questo tutorial impiega il metodo inside-out a scopo illustrativo. Modificate il codice per cambiare il passaggio di larghezza e altezza come esercizio.

La larghezza e l’altezza variabili introducono alcune sottili questioni relative al rendering della mappa. Si è tentati di eseguire tutto ciò che riguarda la configurazione di Leaflet nel gestore on-init, e questo tipicamente funziona con larghezza e altezza fisse. Poiché la larghezza della mappa varia con le dimensioni del browser in questo tutorial, è meglio separare il processo di inizializzazione della mappa tra i gestori del ciclo di vita on-init e after-view-init. Questo è illustrato nei seguenti segmenti di codice da /src/app/maps/map.component.ts .

Prima di tutto, l’identificazione di un DIV contenente l’inizializzazione della mappa viene scaricata su una ViewChild,

@ViewChild('primaryMap', {static: true}) protected mapDivRef: ElementRef;
protected mapDiv: HTMLDivElement;

La maggior parte della configurazione della mappa viene eseguita in ngOnInit,

public ngOnInit(): void
{
// Reference to DIV containing map is used in Leaflet initialization
this.mapDiv = this.mapDivRef.nativeElement;
this.__initializeMap();
this.__renderMap();
this.__showMarkers();
}

La convalida della dimensione della mappa è rinviata a ngAfterViewInit, quando sono disponibili l’intera larghezza e altezza necessarie per far funzionare le tiles della mappa. La variabile map si riferisce alla mappa Leaflet creata nel gestore ngOnInit.

public ngAfterViewInit(): void
{
this.map.invalidateSize();
this.__initMapHandlers();
}

Nota che il gestore di aggiornamento della dimensione della mappa ricomputa le variabili currentWidth e currentHeight della classe, che sono legate agli stili DIV che controllano la larghezza e l’altezza del DIV della mappa. Leaflet usa queste informazioni di larghezza/altezza per ri-rivestire e rendere nuovamente la mappa.

Siccome la definizione della larghezza/altezza della mappa e il ridimensionamento della mappa con i cambiamenti della finestra sono gestiti internamente al componente mappa, viene aggiunto un semplice gestore di ridimensionamento della finestra.

@HostListener('window:resize', )
protected __onResize(event: any): void
{
this.__updateMapSize();
this.map.invalidateSize();
}

Questo potrebbe anche essere gestito da un servizio esterno, eseguito fuori da Angular, e debuggato. Se c’è abbastanza interesse, fornirò un tutorial che illustra la tecnica.

Controlli di mappa

Leaflet permette controlli personalizzati, ma si possono anche usare componenti Angular come controlli di mappa. Crea il componente Angular e usa i CSS per il posizionamento. Ho usato questo in diversi progetti per controlli di zoom altamente personalizzati. Vedi la cartella /src/app/maps/map-control per uno scheletro che può essere usato come punto di partenza.

Riferimento a /src/app/maps/map.component.scss per lo stile rilevante.

Attenzione allo z-index

Se il tiling o qualche altro aspetto della visualizzazione della mappa non sembra funzionare, potrebbe essere un problema di z-index. In passato, ho dovuto rimappare gli z-index semplicemente cambiando i fornitori di tile o anche migrando da Angular 7 ad Angular 8!

Markers

Markers con coordinate note possono essere aggiunti ad una mappa. Definisci le coordinate e poi crea una Leaflet Icon per ciascuna di esse. Le coordinate dei marcatori per questo tutorial sono definite nel componente principale dell’app,

/src/app/app.component.ts

public markers: {lat: number, long: number}; // Map markers (relevance depends on map center)
constructor()
{
// some map markers
this.markers = ;
}

e sono passate come input Angular al componente Map,

/src/app/app.component.html

<app-map ="markers"></app-map>

I marcatori sono resi nel componente mappa,

/src/app/maps/map.component.ts

protected __showMarkers(): void
{
if (this.markers !== undefined && this.markers != null && this.markers.length > 0)
{
// Add markers
const icon = L.icon({
iconUrl: MapIconOptions.mapIcon,
iconSize: MapIconOptions.iconSize,
iconAnchor: MapIconOptions.iconAnchor,
shadowUrl: MapIconOptions.mapShadowIcon,
shadowSize: MapIconOptions.shadowSize,
shadowAnchor: MapIconOptions.shadowAnchor,
});
const n: number = this.markers.length;
let i: number;
let m: L.marker;
let x: number;
let y: number;
for (i = 0; i < n; ++i) {
x = this.markers.lat;
y = this.markers.long;
if (x !== undefined && !isNaN(x) && y !== undefined && !isNaN(y))
{
// okay to add the icon
m = L.marker(, {icon: icon}).addTo(this.map);
}
else
{
// implement your own error handling
console.log('MARKER ERROR, Marker number: ', (i+1), 'x: ', x, ' y: ', y);
}
}
}
}

Interattività

Sono stati aggiunti un paio di gestori per l’interattività di base della mappa, cioè mouse-click e mouse-move. Quest’ultimo aggiorna la posizione corrente della mappa (lat/long) in base alla posizione del mouse.

/src/app/maps/map.component.ts

protected __onMapMouseMove(evt: any): void
{
const lat: string = evt.latlng.lat.toFixed(3);
const long: string = evt.latlng.lng.toFixed(3);
this.mcText = `Latitude: ${lat} &nbsp; &nbsp; Longitude: ${long}`;
}

La stringa che riflette la posizione corrente viene visualizzata nel template del componente della mappa,

/src/app/maps/map.component.html

<div class="mouse-coords">
<span></span>
<span ="mcText"></span>
</div>

Il risultato

Costruisci l’applicazione e dovresti osservare qualcosa di simile a questo screenshot,

Angular versione 8 e Leaflet Map

Muovi il mouse sulla mappa per osservare gli aggiornamenti della posizione del mouse nelle coordinate della mappa.

Spero che questo vi faccia iniziare a lavorare con Angular e Leaflet. Queste due applicazioni lavorano molto bene insieme e c’è un potenziale quasi illimitato per mappe altamente interattive e coinvolgenti.

Buona fortuna con i vostri sforzi per Angular!

Per altre bontà Angular, assicuratevi di controllare l’ultimo episodio del podcast The Angular Show.

ng-conf: The Musical è una conferenza di due giorni dai ragazzi di ng-conf che si terrà il 22 & 23 aprile 2021. Controlla su ng-conf.org

Lascia un commento