And the JavaScript through npm:
npm install leaflet
We can now add a map id to the home.page.ts file:
<ion-content>
<div id="map" style="height:100%;"></div>
</ion-content>
We then import the plugins that we will need:
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { Router } from '@angular/router';
import { Map, tileLayer, marker, icon } from 'leaflet';
import { Http } from '@angular/http';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(public http: Http,
public plt: Platform,
public router: Router) {}
The Http Angular Service and map operator will be used to get the restaurants information (position, name).
From the Leaflet plugin, we have:
Now that we have everything we need, we can start by loading the information:
ngAfterViewInit() {
this.plt.ready().then(() => {
this.http.get('https://oghuxxw1e6.execute-api.us-east-1.amazonaws.com/dev')
.pipe(map(res => res.json()))
.subscribe(restaurants => this.initMap(restaurants));
});
}
We use the http Angular Service to access the data from Amazon then we get the json information and pass it to the following initMap method:
initMap(restaurants) {
const map = new Map('map').setView([33.6396965, -84.4304574], 23);
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
const customMarkerIcon = icon({
iconUrl: 'assets/images/custom-marker-icon.png',
iconSize: [64, 64],
popupAnchor: [0, -20]
});
restaurants.forEach((restaurant) => {
marker([restaurant.position.lat, restaurant.position.lgn], {icon: customMarkerIcon})
.bindPopup(`<b>${restaurant.title}</b>`, { autoClose: false })
.on('click', () => this.router.navigateByUrl('/restaurant'))
.addTo(map).openPopup();
});
}
We start by creating the Leaftlet map by targetting the map id and setting the position and the zoom value.
The tileLayer is then loaded from the OpenStreetMap tile service.
As stated in the documentation, there are other options like {r} that will add "@2x" to the URL to load retina tiles and most tile servers require attribution.
This should be enough to display the map.
We can now create a new customMarkerIcon by passing the url where the icon is located and some positionning information.
The final part now, placing the restaurants and setting them properly.
For each restaurant, we create a new marker by setting the position and the icon that we want to use.
The bindPopup will add a popup with the restaurant's name and the autoClose property will allow us to have multiple popups opened at the same time.
We use the on event listener to specify that when a click is received, the Angular router will navigate to the restaurant page.
Finally we add the newly created marker to the map and open the popup.
We add a new route for the restaurant information:
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadChildren: './home/home.module#HomePageModule' },
{ path: 'restaurant', loadChildren: './restaurant/restaurant.module#RestaurantPageModule' }
];
In the restaurant.page.html, we only display that the restaurant is under construction:
<ion-header>
<ion-toolbar>
<ion-back-button></ion-back-button>
</ion-toolbar>
</ion-header>
<ion-content text-center>
<p> Hello this restaurant is under construction at the moment, come back later!</p>
<img src="assets/images/under-construction.jpg">
</ion-content>
And Voila!