How To Integrate Leaflet Maps in Angular 2022
Leaflet is an open-source JavaScript library for mobile-friendly interactive maps. In this tutorial, we will integrate leaflet maps in angular using ngx-leaflet package.
1. Let's install @angular/cli package.
npm install -g @angular/cli
2. Create a new angular project.
ng new angular-leaflet-maps
cd angular-leaflet-maps
3. Install leaflet, @asymmetrik/ngx-leaflet packages inside the project.
npm install leaflet @asymmetrik/ngx-leaflet
Supported Versions:-
Angular @asymmetrik/ngx-leaflet command
15 15 npm i @asymmetrik/ngx-leaflet
14 14 npm i @asymmetrik/ngx-leaflet@14
13 13 npm i @asymmetrik/ngx-leaflet@13
10 8 npm i @asymmetrik/ngx-leaflet@8
9 7 npm i @asymmetrik/ngx-leaflet@7
Checkout:- https://github.com/Asymmetrik/ngx-leaflet/blob/HEAD/CHANGES.md
4. Install @types/leaflet package.
npm install --save-dev @types/leaflet
5. Open src/styles.css and import leaflet.css
@import "~leaflet/dist/leaflet.css";
6. Open app.module.ts and import LeafletModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { LeafletModule } from '@asymmetrik/ngx-leaflet';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
LeafletModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
7. Open angular.json and update assets.
...
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angular-leaflet-maps",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*",
"input": "./node_modules/leaflet/dist/images",
"output": "assets/"
}
],
this object
{
"glob": "**/*",
"input": "./node_modules/leaflet/dist/images",
"output": "assets/"
}
8. Open app.component.ts and add the following code.
import { Component } from '@angular/core';
import * as Leaflet from 'leaflet';
Leaflet.Icon.Default.imagePath = 'assets/';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
map!: Leaflet.Map;
markers: Leaflet.Marker[] = [];
options = {
layers: [
Leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
})
],
zoom: 16,
center: { lat: 28.626137, lng: 79.821603 }
}
initMarkers() {
const initialMarkers = [
{
position: { lat: 28.625485, lng: 79.821091 },
draggable: true
},
{
position: { lat: 28.625293, lng: 79.817926 },
draggable: false
},
{
position: { lat: 28.625182, lng: 79.81464 },
draggable: true
}
];
for (let index = 0; index < initialMarkers.length; index++) {
const data = initialMarkers[index];
const marker = this.generateMarker(data, index);
marker.addTo(this.map).bindPopup(`<b>${data.position.lat}, ${data.position.lng}</b>`);
this.map.panTo(data.position);
this.markers.push(marker)
}
}
generateMarker(data: any, index: number) {
return Leaflet.marker(data.position, { draggable: data.draggable })
.on('click', (event) => this.markerClicked(event, index))
.on('dragend', (event) => this.markerDragEnd(event, index));
}
onMapReady($event: Leaflet.Map) {
this.map = $event;
this.initMarkers();
}
mapClicked($event: any) {
console.log($event.latlng.lat, $event.latlng.lng);
}
markerClicked($event: any, index: number) {
console.log($event.latlng.lat, $event.latlng.lng);
}
markerDragEnd($event: any, index: number) {
console.log($event.target.getLatLng());
}
}
Note:- you can also use mergeOptions() method instead of imagePath property.
LeafLet.Icon.Default.mergeOptions({
iconRetinaUrl: 'assets/marker-icon-2x.png',
iconUrl: 'assets/marker-icon.png',
shadowUrl: 'assets/marker-shadow.png'
});
In the above code, you also use custom icons.
9. Open app.component.html and add the following code.
<div class="map-container"
leaflet
[leafletOptions]="options"
(leafletMapReady)="onMapReady($event)"
(leafletClick)="mapClicked($event)">
</div>
10. Open styles.css file and add this css.
.map-container {
height: 400px;
}
#Add a marker
const data = {
position: { lat: 28.625043, lng: 79.810135 },
draggable: true
}
const marker = this.generateMarker(data, this.markers.length - 1);
marker.addTo(this.map).bindPopup(`<b>${data.position.lat}, ${data.position.lng}</b>`);
this.markers.push(marker);
#Remove a marker
this.map.removeLayer(this.markers[index])
this.markers.splice(index, 1)
#Update a marker
this.markers[index].setLatLng({ lat: 28.625043, lng: 79.810135 });
getIcon() - get marker icon
getLatLng() - get marker position
setIcon() - set marker icon
setLatLng() - set marker position
setOpacity(opacity) - set marker opacity
11. Finally run the project.
ng serve --o
it will open http://localhost:4200 in the browser.
Extras:- Reverse Geocoding
12. Install leaflet-control-geocoder npm package.
npm i leaflet-control-geocoder
13. Import leaflet-control-geocoder
import { Component } from '@angular/core';
import * as Leaflet from 'leaflet';
import "leaflet-control-geocoder";
14. Create a function.
getAddress(lat: number, lng: number) {
const geocoder = (Leaflet.Control as any).Geocoder.nominatim();
return new Promise((resolve, reject) => {
geocoder.reverse(
{ lat, lng },
this.map.getZoom(),
(results: any) => results.length ? resolve(results[0].name) : reject(null)
);
})
}
You can use this function by passing lat and lng.
async mapClicked($event: any) {
console.log($event.latlng.lat, $event.latlng.lng);
const address = await this.getAddress($event.latlng.lat, $event.latlng.lng);
console.log(address)
}
Checkout my full angular-leaflet-maps example.
https://github.com/ultimateakash/angular-leaflet-maps
If you facing any issues. don't hesitate to comment below.
Thanks.
Leave Your Comment