Lorsqu’il s’agit de présenter des informations contenant des données géographiques, la cartographie s’impose naturellement comme une solution à envisager. Ce fut mon cas récemment à l’occasion du développement de Citizen Map, une cartographie des initiatives et des projets citoyens au sein de l’Eurométropole Lille-Kortrijk-Tournai.
Pour ce faire, je me suis appuyé sur une librairie Javascript open source de cartographie nommée Leaflet. De nombreuses ressources expliquant l’utilisation de cette librairie sont disponibles sur internet pour un développement en Javascript. Sauf que dans le cas de Citizen Map, j’ai fait le choix de développer la solution avec un framework front-end basé sur TypeScript : Angular. Malheureusement peu de ressources expliquent l’utilisation de leaflet dans cette configuration. La bonne nouvelle : cet article est là pour vous expliquer comment utiliser leaflet avec le framework Angular.
Angular ou AngularJS ?
Angular, à ne pas confondre avec son prédécesseur AngularJS, est un framework front-end proposé par Google. Angular est une réécriture complète (à partir de la version 2) du framework AngularJS (première version du framework) à commencer par le langage de programmation. En effet, AngularJS se base sur le traditionnel Javascript ; Angular quant à lui s’appuie sur TypeScript, un sur-ensemble de Javascript.
Cela fait beaucoup d’informations dans un seul paragraphe ; n’hésitez pas à cliquer sur les différents liens ci-dessus pour approfondir le sujet, si besoin. Toutefois, je vous rassure, cela ne vous empêchera pas de poursuivre la lecture de cet article.
Création d’un projet Angular
Pour créer notre premier projet Angular, nous allons utiliser Angular CLI, un outil en ligne de commande qui va grandement nous faciliter la tâche. Angular CLI s’installe via le gestionnaire de paquet NPM. Si vous êtes étranger à tout ça, je vous conseille de lire mon article sur les API et Node.JS.
Depuis la console de votre terminal, tapez les commandes suivantes :
npm install -g @angular/cli ng new frugal-map cd frugal-map ng serve
La première commande installe Angular CLI, la seconde génère une application Angular nommée frugal-map, la troisième vous permet d’entrer dans le répertoire de l’application nouvellement créée et enfin « ng serve » lance un serveur avec votre application disponible sur http://localhost:4200
Angular CLI a généré un certain nombre de fichiers. Nous allons nous rendre dans le dossier app qui se trouve lui même dans le dossier src. A l’aide de votre éditeur de texte préféré, vous allez modifier le contenu du fichier app.component.html.
Remplacez le contenu par celui ci-dessous :
<div style="text-align:center"> <h1> Bienvenue sur Frugal Map </h1> </div>
Vous devriez voir la page d’accueil de l’application modifiée avec notre message de bienvenue.
Installation de la librairie Leaflet
Pour pouvoir utiliser la librairie Leaflet, nous devons l’installer via NPM. Nous devons également installer sa définition en TypeScript, car comme évoqué ci-dessus, le framework Angular est basé sur le langage TypeScript.
Pour ce faire, entrez la commande ci-dessous :
npm --save install leaflet @types/leaflet
Ensuite, nous allons indiquer à notre application Angular, le dossier dans lequel se trouvent les feuilles de style (css). Cela se fait dans le fichier angular-cli.json disponible à la racine de notre projet.
"styles": [ "styles.css", "../node_modules/leaflet/dist/leaflet.css" ],
Enfin, nous allons indiquer à notre application, qu’elle doit utiliser la version TypeScript de la librairie Leaflet. C’est très simple, il suffit d’ajouter « leaflet » dans le tableau « types » qui se trouve dans le fichier tsconfig.app.json.
{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/app", "baseUrl": "./", "module": "es2015", "types": [ "leaflet" ] }, "exclude": [ "test.ts", "**/*.spec.ts" ] }
Il faudra relancer l’application (CTRL + C) puis « ng serve » de nouveau pour que la configuration soit appliquée.
Configuration de la carte
Nous allons maintenant retourner dans le fichier app.component.html pour déclarer le conteneur de notre carte. Nous donnons comme id à ce conteneur « frugalmap ».
<div style="text-align:center"> <h1> Bienvenue sur Frugal Map </h1> </div> <!-- Déclaration du conteneur de la carte avec l'id "frugalmap" --> <div id="frugalmap"> </div>
Dans le fichier app.component.css, nous allons indiquer les dimensions de ce conteneur et donc de notre carte.
#frugalmap { height: 600px; width: 100% }
La suite des opérations va se dérouler dans le fichier TypeScript app.component.ts dans lequel nous allons déclarer la carte et la configurer.
Vous trouverez ci-dessous ce fichier dans sa version finale avec les commentaires explicatifs :
// Ajouter OnInit pour effectuer des opérations à l'initialisation du composant. import { Component, OnInit } from '@angular/core'; import * as L from 'leaflet'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) // Implémenter OnInit export class AppComponent implements OnInit { // Fonction d'initialisation du composant. ngOnInit() { // Déclaration de la carte avec les coordonnées du centre et le niveau de zoom. const myfrugalmap = L.map('frugalmap').setView([50.6311634, 3.0599573], 12); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: 'Frugal Map' }).addTo(myfrugalmap); } }
Nous avons commencé par importer OnInit pour pouvoir déclarer notre carte lors de l’initialisation de l’application (du composant pour être plus précis). Son implémentation requiert la déclaration d’une fonction ngOnInit au sein de laquelle nous instancions la carte.
À ce stade, vous devriez voir s’afficher une carte juste en dessous de notre message de bienvenue.
Ajouter des marqueurs sur notre carte
En règle générale, lorsqu’on utilise une cartographie, c’est pour afficher des données géographiques… Nous allons donc ajouter des marqueurs sur notre carte.
Pour ce faire c’est très simple. Toujours dans la fonction ngOnInit, ajouter le code ci-dessous :
const myIcon = L.icon({ iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png' }); L.marker([50.6311634, 3.0599573], {icon: myIcon}).bindPopup('Je suis un Frugal Marqueur').addTo(myfrugalmap).openPopup();
Voilà, nous avons notre application angular avec une cartographie basée sur Leaflet ainsi qu’un marqueur !
Bonus avec des données réelles
Avant de vous laisser, je vous propose une petite section bonus dans laquelle nous allons utiliser des données géographiques réelles récupérées via une API et les afficher sur notre carte.
Nous allons utiliser le module HttpClient disponible sur Angular depuis sa version 4.3. Nous allons devoir importer ce module dans notre application afin de pouvoir l’utiliser. Cela se fera dans le fichier app.module.ts.
Ajouter la ligne :
// Import HttpClientModule from @angular/common/http import {HttpClientModule} from '@angular/common/http';
Ensuite dans le tableau imports de ce même fichier, ajouter « HttpClientModule »:
imports: [ BrowserModule, HttpClientModule ],
Nous pouvons maintenant utiliser le module HttpClientModule pour interroger une API. Je vous propose d’utiliser l’API Open Data de la métropole lilloise et de récupérer toutes les bornes podotactiles. Les bornes podotactiles servent de signalisation, de guidage et de repérage pour les non et mal-voyants.
Revenons à notre fichier app.component.ts dans lequel nous allons importer HttpClient :
import { HttpClient } from '@angular/common/http';
Nous allons ensuite ajouter un constructeur à l’intérieur de la classe AppComponent pour injecter HttpClient dans notre composant.
export class AppComponent implements OnInit { constructor(private http: HttpClient){ } ngOnInit() { ...
Il ne nous reste plus maintenant qu’à effectuer une requête GET pour obtenir les informations de localisation des bornes podotactiles dans la métropole lilloise à cette adresse.
Je vous laisse ci-dessous un exemple de code (très simplifié) pour faire cela :
// Ajouter OnInit pour effectuer des opérations à l'initialisation du composant. import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import * as L from 'leaflet'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) // Implémenter OnInit export class AppComponent implements OnInit { constructor(private http: HttpClient) {} // Fonction d'initialisation du composant. ngOnInit() { // Déclaration de la carte avec les coordonnées du centre et le niveau de zoom. const myfrugalmap = L.map('frugalmap').setView([50.6311634, 3.0599573], 12); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: 'Frugal Map' }).addTo(myfrugalmap); const myIcon = L.icon({ iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png' }); this.http.get('https://opendata.lillemetropole.fr/api/records/1.0/search/?dataset=bornes-podotactiles').subscribe((data: any) => { data.records.forEach(podotactile => { L.marker([podotactile.geometry.coordinates[1], podotactile.geometry.coordinates[0]], {icon: myIcon}).addTo(myfrugalmap); }); }); } }
Normalement votre application devrait ressembler à l’image ci-dessous :
Voilà c’est tout pour ce tutoriel !
Si vous avez des questions ou des remarques, n’hésitez pas à laisser un commentaire.
Comme d’habitude, si des erreurs se sont glissées dans l’article, n’hésitez pas à nous en faire part.
Pour être informé des prochains articles, rendez-vous sur Twitter.
Merci, et à très bientôt sur Frugal Prototype
Ali Benfattoum
Intrapreneur, Tech Enthusiast, IoT Expert, Smart City Specialist…
Suivez moi sur @alifrugal
Related Posts
27 décembre 2016
Une API en 15 minutes avec MongoDB, Mongoose et Node.js
Afin de conclure la série d'articles…
14 août 2016
Développez votre propre API avec Node.js et Express
Chose promise, chose due : nous allons…
Hello,
Merci chef!!! Je cherchais justement une base pour me lancer avec leaflet et angular (>= 2). Donc si je démarre avec ton « architecture » je vais pouvoir utiliser toutes les fonctions leaflet, il n y a pas de contrainte due à cette « nouvelle » version d’angular?
Salut,
Je l’ai testé avec la version 5 d’Angular, aucun souci.
Si tu rencontres un problème dans la mise en place n’hésite pas à laisser un autre commentaire.
A+
Ali
Hello Ali,
Avez-vous rencontrer le problème lié à la position des markeurs qu’on zoome/dé-zoome la carte, stp ? Avez-vous une solution stp ?
Merci,
Bonjour Abder,
Non je n’ai pas rencontré ce type de problème.
Pouvez vous m’en dire plus sur le problème rencontré ?
Ali
Bonjour,
j’ai le même soucis, quand c’est dézoomé (par exemple à 12 comme dans votre exemple), le marqueur n’est clairement au bon endroit (dans mon cas au milieu d’un lac). En zoomant on se rapproche de plus en plus de l’endroit correct mais du coup c’est pas vraiment utilisable car ça donne une vue d’ensemble très faussée. Auriez-vous une piste pour résoudre ce problème ?
Merci pour le tuto qui est top !
Bonjour,
Oui, comme nous utilisons un custom marker, il y a des options supplémentaires pour corriger cela lors de la création de l’icon, notamment en spécifiant la taille de l’icône et son ancrage :
const myIcon = L.icon({
iconUrl: ‘https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png’,
iconSize: [25, 41], // taille de l’icône
iconAnchor: [25, 41], // point d’ancrage (la position du marqueur)
});
Hello 🙂
Un grand merci Ali pour ce super article.
Pour ma part, j’ai repris ta solution Ali.
Cependant, la correction semble être la bonne en positionnant l’attribut iconAnchor comme tel :
const myIcon = L.icon({
iconUrl: ‘https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png’,
iconSize: [25, 41], // taille de l’icône
iconAnchor: [12.5, 41], // point d’ancrage
});
En divisant la largeur de l’icône par 2.
A dispo 🙂
Correction de l’explication :
En divisant la coordonnée X du point d’ancrage par 2, sur la largeur donc.
Bonjour,
Y a t-il possibilité d’afficher des données depuis une base MySQL et d’enregistrer aussi.
Bonjour,
Merci pour cet article. Je cherche à ajouter le plugin « Leaflet-easyPrint » à ma carte dans un projet Angular.
(http://leafletjs.com/plugins.html)
Savez-vous par hasard si cela est possible ?
Merci d’avance
Il faudrait vérifier que le plugin existe en version typescript ce qui faciliterait son intégration.
Bonjour,
Merci pour cet article très utile !
Deux points :
– De mon côté, le css de Leaflet n’est trouvé que si le chemin renseigné est « node_modules/leaflet/dist/leaflet.css » (sans ../ ) dans le fichier angular.json (sous angular v6)
– Et sinon je cherche depuis un moment (et ça m’a coûté quelques cheveux) à rajouter la lib Leaflet.awesome-markers en suivant la même procédure que pour ajouter Leaflet sous angular mais j’obtiens sans cesse une erreur « Module not found: Error: Can’t resolve … », as-tu déjà rencontré ce type de problème ? Je n’ai strictement rien trouvé à ce sujet sur Stackoverflow ou ailleurs …
Merci d’avance pour ton aide !
Flo
Bonjour,
Je suis intéressé par ton expérience avec angular 6.
J’ai effectivement dû faire le meme changement que toi pour le css.
Par contre je rencontre quelques souci en essayant de l’utiliser
Quand j’essaye de l’utiliser ainsi:
import * as L from ‘leaflet’;
ngOnInit() {
const siteMap = L.map(‘siteMap’).setView([50.6311634, 3.0599573], 12);
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’, {
attribution: ‘Site Map’
}).addTo(siteMap);}
j’ai l’erreur:
error TS2304: Cannot find name ‘L’.
J’utilise Leaflet 1.3.3
Merci par avance
Salut les amis
j’ai placé un marqueur sur ma carte et je récupère les coordonnées liées à la position de mon utilisateur après qu’il ait bougé le marqueur. le code est ici:
https://github.com/salomonayah/leafletmap
c’est gratuit !
Super tutoriel.
Dans mon cas, je veux intégré la recherche sur ma carte et je suis tombé sur le plugin leaflet-search . Mais ça ne passe pas. Pourrais-je avoir une piste avec Angular 6 ?
Merci de m’aider
Merci !
Top tuto ! en moins de 5 min une carte fonctionnelle
Bonjour, j’ai testé Leaflet en Angular , aucun soucis cependant en Angular 7 la carte s’affiche mais est complètement dissocié. Avez-vous un correctif ?
Merci par avance.
Bonjour Ali,
Peux-tu faire un exemple comment enregistrer un
marker ou autre forme dans mongodb avec lien API ?
Bonjour merci pour ce tuto,
J’aimerais savoir comment implementer le tracer d’un itineraire avec leaflet.
Merci bien
Bonjour,
J’ai bien compris ,mais j’aimerais savoir comment on affiche une ville particulière comme Bordeaux ou Lille par exemple.
Merci
Excellent !! Merci pour le partage
Bonjour Ali,
J’espère que vous allez bien j’ai bien aimé votre tuto,est ce que tu peux m’aidé avec un tuto sur geofire et angular.
j’ai fait des recherche sur le net aucun résultat
merci d’avance .
Merci pour votre tuto vraiment ça vraiment m’a bien aidé a commencer mon application
est ce que tu peux m’aider avec un tuto pour afficher des données stockées dans une base de données Postgresql
Bonjour,
Est ce que on peut avoir une carto avec leaflet en mode offline ??
Merciiii beaucoup Ali
Hello, j’ai une petite question sur leaflet et angular.
Est t’il possible d’injecter un composant a l’interieur d’un popup (bindPopup) ?
Je ne trouve pas l’info /: