Acest articol este orientat către dezvoltatorii Angular începători care doresc să integreze Leaflet în aplicațiile lor. Integrarea dependențelor de la terți în Angular poate fi de la trivială la problematică. În timp ce Leaflet tinde mai mult spre partea trivială, hărțile care se ajustează în mod fluid în funcție de dimensiunea browserului pot prezenta unele probleme de configurare în raport cu ciclul de viață Angular.
Înainte de a începe deconstrucția, îndreptați-vă browserul prietenos, de cartier, către următorul Github.
Acum, puteți urmări proiectul sau îl puteți folosi ca bază pentru propriile aplicații.
Background
Acest tutorial presupune o cantitate mică de cunoștințe anterioare despre Leaflet, dar nu mai mult decât este exprimat în Leaflet Quickstart Guide.
ArcGis este folosit pentru tiling în aplicația tratată în acest articol (pachetul esri-leaflet este instalat din npm).
Angular Setup
Mai puțin trebuie făcut după omniprezenta instalare npm. Stilurile Leaflet necesare sunt puse la dispoziție prin intermediul fișierului angular.json,
"styles": ,
Am avut rezultate mixte cu @types/leaflet, așa că această aplicație nu exploatează tipizările din motive de simplitate. Tăblițele Leaflet și ESRI sunt importate așa cum se arată mai jos,
import * as esri from 'esri-leaflet';
import * as L from 'leaflet';
O hartă Leaflet, de exemplu, este temporar tipizată ca oricare; nu ezitați să întăriți tipizările ca un exercițiu după ce ați deconstruit tutorialul.
Coordonatele centrului unei hărți sunt importante pentru inițializarea hărții. Multe demonstrații codifică în hardcode această informație. Ca o alternativă, acest tutorial ilustrează modul de injectare a coordonatelor centrului hărții folosind jetoanele de injecție ale Angular.
O coordonată este un punct bidimensional pe o hartă, reprezentat prin latitudine și longitudine. Un InjectionToken pentru o coordonată poate fi creat așa cum este ilustrat în fișierul /src/app/tokens.ts,
import { InjectionToken } from '@angular/core';
export const INIT_COORDS = new InjectionToken<{lat: number, long: number}>('INIT_COORDS');
INIT_COORDS este utilizat în modulul /src/app/app.ts.ts pentru a efectua furnizarea (sau definirea) efectivă (lat/long),
providers: ,
Aceasta mută definiția centrului hărții la cel mai înalt nivel în aplicația Angular (unde este ușor de văzut și aproape autodocumentată).
Pentru a injecta această coordonată în aplicație, importați INIT_COORDS din fișierul tokens și injectați-o dintr-un constructor de clasă. Acest lucru este ilustrat în fișierul /src/app/map.component.ts (componenta principală a hărții din acest tutorial),
constructor( @Inject(INIT_COORDS) protected _initCoords: {lat: number, long: number} )
Componenta hartă
Aplicația tratată în acest articol afișează o hartă cu înălțime fixă, cu o lățime care se extinde pe întreaga fereastră a browserului. Harta se redesenează pe măsură ce fereastra se redimensionează. Unele marcaje sunt, de asemenea, redate deasupra dalei hărții.
Harta este integrată în aplicație prin șablonul componentei principale a aplicației, așa cum se arată mai jos
/src/app/app.component.html
<app-map ="markers"></app-map>
și codul sursă al componentei hartă se găsește în /src/app/maps/map.component.ts .
Harta este redată într-un container (DIV) care se află în prezent în șablonul componentei de hartă,
/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>
Dacă lățimea și înălțimea DIV-ului care o conține sunt fixe, atunci dalele hărții pot fi redate într-un punct timpuriu al ciclului de viață al componentei. Sunt posibile două abordări pentru transmiterea lățimii și înălțimii variabile, outside-in și inside-out. Metoda outside-in definește Angular Inputs pentru lățime și înălțime. Componenta părinte este responsabilă pentru comunicarea lățimii și înălțimii către componenta de hartă. Abordarea inside-out definește lățimea și înălțimea în interiorul componentei hartă și „transmite” aceste informații șablonului său. Majoritatea aplicațiilor utilizează abordarea outside-in. Acest tutorial folosește metoda inside-out în scop ilustrativ. Modificați codul pentru a schimba transmiterea lățimii și înălțimii ca exercițiu.
Lățimea și înălțimea variabile introduc unele probleme subtile referitoare la redarea hărții. Este tentant să efectuați tot ceea ce este legat de configurarea Leaflet în gestionarul on-init, iar acest lucru funcționează de obicei cu lățime și înălțime fixe. Deoarece lățimea hărții variază în funcție de dimensiunea browserului în acest tutorial, este mai bine să separați procesul de inițializare a hărții între gestionarii ciclului de viață on-init și after-view-init. Acest lucru este ilustrat în următoarele segmente de cod din /src/app/maps/map/map.component.ts .
În primul rând, identificarea unui DIV de conținut pentru inițializarea hărții este transferată către un ViewChild,
@ViewChild('primaryMap', {static: true}) protected mapDivRef: ElementRef;
protected mapDiv: HTMLDivElement;
Cei mai mulți dintre parametrii hărții sunt realizați în 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();
}
Invalidarea dimensiunii hărții este amânată pentru ngAfterViewInit, atunci când este disponibilă întreaga lățime și înălțime necesară pentru ca plăcile hărții să funcționeze. Variabila map se referă la harta Leaflet creată în gestionarul ngOnInit.
public ngAfterViewInit(): void
{
this.map.invalidateSize();
this.__initMapHandlers();
}
Rețineți că gestionarul de actualizare a dimensiunii hărții recalculează variabilele currentWidth și currentHeight ale clasei, care sunt legate de stilurile DIV care controlează lățimea și înălțimea DIV-ului hărții. Leaflet utilizează aceste informații de lățime/înălțime pentru a redimensiona și reda din nou harta.
Din moment ce definirea lățimii/înălțimii hărții și redimensionarea hărții cu modificări ale ferestrei sunt gestionate intern în componenta de hartă, se adaugă un simplu gestionar de redimensionare a ferestrei.
@HostListener('window:resize', )
protected __onResize(event: any): void
{
this.__updateMapSize();
this.map.invalidateSize();
}
Acest lucru ar putea fi gestionat, de asemenea, de un serviciu extern, executat în afara Angular, și debusolat. Dacă există suficient interes, voi furniza un tutorial care să ilustreze tehnica.
Controale de hartă
Leaflet permite controale personalizate, dar puteți utiliza și componente Angular ca și controale de hartă. Creați componenta Angular și folosiți CSS pentru poziționare. Am folosit acest lucru în mai multe proiecte pentru controale de zoom foarte personalizate. Consultați folderul /src/app/maps/map-control pentru un schelet care poate fi folosit ca punct de plecare.
Referiți-vă la /src/app/maps/map.component.scss pentru stilizarea relevantă.
Atenție la z-index
Dacă nu pare să funcționeze modul de aranjare sau un alt aspect al afișării hărților, este posibil să fie o problemă cu z-index. În trecut, am fost nevoit să refac indicii z-indicele pur și simplu din cauza schimbării furnizorilor de tile-uri sau chiar a migrării de la Angular 7 la Angular 8!
Markere de hartă
Markers with known coordinates may be added to a map. Definiți coordonatele și apoi creați o pictogramă Leaflet pentru fiecare dintre ele. Coordonatele markerilor pentru acest tutorial sunt definite în componenta principală a aplicației,
/src/app/app.component.ts
public markers: {lat: number, long: number}; // Map markers (relevance depends on map center)
constructor()
{
// some map markers
this.markers = ;
}
și sunt transmise ca Angular Input către componenta Map,
/src/app/app.component.ts
public markers: {lat: number, long: number}; // Map markers (relevance depends on map center)
constructor()
{
// some map markers
this.markers = ;
}
și sunt transmise ca Angular Input către componenta Map,
/src/app/app.component.html
<app-map ="markers"></app-map>
Markerii sunt redate în componenta de hartă,
/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);
}
}
}
}
Interactivitate
Au fost adăugați pentru dumneavoastră câțiva gestionari pentru interactivitatea de bază a hărții, și anume mouse-click și mouse-move. Acesta din urmă actualizează poziția curentă a hărții (lat/long) pe baza poziției mouse-ului.
/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} Longitude: ${long}`;
}
Șirul de caractere care reflectă poziția curentă este afișat în șablonul componentei hartă,
/src/app/maps/map.component.ts
/src/app/map/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} Longitude: ${long}`;
}
.html
<div class="mouse-coords">
<span></span>
<span ="mcText"></span>
</div>
Rezultat
Construiți aplicația și ar trebui să observați ceva asemănător cu această captură de ecran,