Pas à pas – Insérer une carte OpenStreetMap sur votre site

11 mai 2018 - : HTML Javascript jQuery - : 36 commentaire.s

 20 3

Google a annoncé il y a quelques jours que son API Google Maps Javascript va devenir payante pour un grand nombre de développeurs, habitués jusqu’à maintenant à une gratuité totale.

Pour être clair, de nombreux sites conserveront la gratuité, mais vous ne serez pas à l’abri d’une facturation si votre site venait à connaître un pic de fréquentation.

Voici une alternative gratuite à Google Maps pour votre site et une mise en œuvre reprenant les exemples indiqués dans l’article Pas à Pas – Insérer une carte Google Maps avec l’API Google Maps Javascript

OpenStreetMap

Pour commencer, parlons un peu d’OpenStreetMap. Il s’agit d’un projet international fondé en 2004 dans le but de créer une carte libre du monde.

En plus de fournir des cartes, open source, de nombreuses API permettent de rendre leur utilisation très proche de Google Maps, ce qui en fait une alternative très crédible.

Initialisation de l’API

Carte OpenStreetMap

Pour initialiser l’API, nous devrons utiliser une bibliothèque Javascript qui nous donnera toutes les ressources pour intéragir avec les serveurs d’OpenStreetMap. La librairie que j’utilise est Leaflet. Nous allons créer un fichier HTML contenant le code ci-dessous

<!DOCTYPE html>
<html>
	<head>
        <meta charset="utf-8">
        <!-- Nous chargeons les fichiers CDN de Leaflet. Le CSS AVANT le JS -->
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
            crossorigin="" />
        <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
            crossorigin=""></script>
		<script type="text/javascript">
			// On initialise la latitude et la longitude de Paris (centre de la carte)
			var lat = 48.852969;
			var lon = 2.349903;
			var macarte = null;
			// Fonction d'initialisation de la carte
			function initMap() {
				// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
                macarte = L.map('map').setView([lat, lon], 11);
                // Leaflet ne récupère pas les cartes (tiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
                L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
                    // Il est toujours bien de laisser le lien vers la source des données
                    attribution: 'données © <a href="//osm.org/copyright">OpenStreetMap</a>/ODbL - rendu <a href="//openstreetmap.fr">OSM France</a>',
                    minZoom: 1,
                    maxZoom: 20
                }).addTo(macarte);
            }
			window.onload = function(){
				// Fonction d'initialisation qui s'exécute lorsque le DOM est chargé
				initMap(); 
			};
		</script>
		<style type="text/css">
			#map{ /* la carte DOIT avoir une hauteur sinon elle n'apparaît pas */
				height:400px;
			}
		</style>
		<title>Carte</title>
	</head>
	<body>
		<div id="map">
			<!-- Ici s'affichera la carte -->
		</div>
	</body>
</html>

Ajout d’un marqueur

Bien sûr, cette carte ne fait apparaître aucun marqueur de position. Il pourrait être intéressant de mettre un marqueur aux coordonnées que nous avons entrées.

Carte OpenStreetMap avec marqueur

 

Pour ce faire, nous allons insérer le code d’ajout de marqueur ci-dessous juste avant la fermeture de notre fonction initMap (au dessus de l’accolade située en ligne 26 sur le code ci-dessus).

// Nous ajoutons un marqueur
var marker = L.marker([lat, lon]).addTo(macarte);
 

Ajout de plusieurs marqueurs

Bien sûr, nous pourrions avoir besoin de plusieurs marqueurs. OpenStreetMap nous propose donc d’ajouter ces différents points en effectuant une boucle sur un tableau contenant les différentes coordonnées.

Carte OpenStreetMap avec marqueurs

Dans notre exemple, nous aurons 4 points correspondant à 4 villes. Nous allons initialiser un tableau json « en dur » et le parcourir pour placer les différents marqueurs.

Voici la fonction initMap mise à jour, les lignes ajoutées sont en surbrillance.

// Nous initialisons une liste de marqueurs
var villes = {
	"Paris": { "lat": 48.852969, "lon": 2.349903 },
	"Brest": { "lat": 48.383, "lon": -4.500 },
	"Quimper": { "lat": 48.000, "lon": -4.100 },
	"Bayonne": { "lat": 43.500, "lon": -1.467 }
};
// Fonction d'initialisation de la carte
function initMap() {
	// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
	macarte = L.map('map').setView([lat, lon], 11);
	// Leaflet ne récupère pas les cartes (tiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
	L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
		// Il est toujours bien de laisser le lien vers la source des données
		attribution: 'données © OpenStreetMap/ODbL - rendu OSM France',
		minZoom: 1,
		maxZoom: 20
	}).addTo(macarte);
	// Nous parcourons la liste des villes
	for (ville in villes) {
		var marker = L.marker([villes[ville].lat, villes[ville].lon]).addTo(macarte);
	}               	
}

Les bulles d’information

Il peut être nécessaire, dans certaines utilisations des cartes OpenStreetMap, de faire apparaître une bulle d’information lorsque l’utilisateur cliquera sur le marqueur.

Carte OpenStreetMap avec popups

Dans l’API, ces bulles sont appelées « Popup ». Elles doivent être « attachées » à chacun des marqueurs et s’activer au clic de l’utilisateur.

Voici le code à ajouter pour nous permettre d’afficher la ville correspondant au marqueur

// Nous parcourons la liste des villes
for (ville in villes) {
	var marker = L.marker([villes[ville].lat, villes[ville].lon]).addTo(macarte);
	// Nous ajoutons la popup. A noter que son contenu (ici la variable ville) peut être du HTML
	marker.bindPopup(ville);
}               	

Les marqueurs personnalisés

L’API Leaflet permet de personnaliser les marqueurs affichés sur la carte.

Avant d’écrire du code, il sera nécessaire de créer les images correspondantes.

Dans l’exemple suivant, nous allons utiliser une image appelée « autres.png », d’une taille de 64 par 64 pixels, qui sera accessible depuis le chemin http://localhost/carte/icons, ce qui donnera un résultat comme celui ci-dessous.

Carte OpenStreetMap avec marqueurs personnalisés

Voici le code à modifier

function initMap() {
	// Nous définissons le dossier qui contiendra les marqueurs
	var iconBase = 'http://localhost/carte/icons/';
	// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
	macarte = L.map('map').setView([lat, lon], 11);
	// Leaflet ne récupère pas les cartes (tiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
	L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
		// Il est toujours bien de laisser le lien vers la source des données
		attribution: 'données © OpenStreetMap/ODbL - rendu OSM France',
		minZoom: 1,
		maxZoom: 20
	}).addTo(macarte);
	// Nous parcourons la liste des villes
	for (ville in villes) {
		// Nous définissons l'icône à utiliser pour le marqueur, sa taille affichée (iconSize), sa position (iconAnchor) et le décalage de son ancrage (popupAnchor)
		var myIcon = L.icon({
			iconUrl: iconBase + "autres.png",
			iconSize: [50, 50],
			iconAnchor: [25, 50],
			popupAnchor: [-3, -76],
		});
		var marker = L.marker([villes[ville].lat, villes[ville].lon], { icon: myIcon }).addTo(macarte);
		marker.bindPopup(ville);
	}               	
}

Le regroupement de marqueurs

Lorsque de nombreux marqueurs se trouvent sur une carte, il peut être nécessaire de les regrouper pour faciliter sa lecture, ceux-ci apparaissant séparés lorsque le zoom le permet.

Carte OpenStreetMap avec regroupement de marqueurs

Les groupes de marqueurs s’appellent des « clusters ».

L’API Leaflet ne permet pas de faire des regroupements de marqueurs. Nous utiliserons une bibliothèque complémentaire appelée Markercluster.

Le code de notre page complète ressemblera à ceci. Les lignes ajoutées ou modifiées sont indiquées

<!DOCTYPE html>
<html>
	<head>
        <meta charset="utf-8">
        <!-- Nous chargeons les fichiers CDN de Leaflet. Le CSS AVANT le JS -->
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
            crossorigin="" />
        <link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet.markercluster@1.3.0/dist/MarkerCluster.css" />
        <link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet.markercluster@1.3.0/dist/MarkerCluster.Default.css" />
        <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
            crossorigin=""></script>
        <script type='text/javascript' src='https://unpkg.com/leaflet.markercluster@1.3.0/dist/leaflet.markercluster.js'></script>
		<script type="text/javascript">
			// On initialise la latitude et la longitude de Paris (centre de la carte)
			var lat = 48.852969;
			var lon = 2.349903;
			var macarte = null;
            var markerClusters; // Servira à stocker les groupes de marqueurs
            // Nous initialisons une liste de marqueurs
            var villes = {
                "Paris": { "lat": 48.852969, "lon": 2.349903 },
                "Brest": { "lat": 48.383, "lon": -4.500 },
                "Quimper": { "lat": 48.000, "lon": -4.100 },
                "Bayonne": { "lat": 43.500, "lon": -1.467 }
            };
			// Fonction d'initialisation de la carte
   			function initMap() {
                // Nous définissons le dossier qui contiendra les marqueurs
                var iconBase = 'http://localhost/carte/icons/';
				// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
                macarte = L.map('map').setView([lat, lon], 11);
                markerClusters = L.markerClusterGroup(); // Nous initialisons les groupes de marqueurs
                // Leaflet ne récupère pas les cartes (tiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
                L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
                    // Il est toujours bien de laisser le lien vers la source des données
                    attribution: 'données © <a href="//osm.org/copyright">OpenStreetMap</a>/ODbL - rendu <a href="//openstreetmap.fr">OSM France</a>',
                    minZoom: 1,
                    maxZoom: 20
                }).addTo(macarte);
                // Nous parcourons la liste des villes
                for (ville in villes) {
	                // Nous définissons l'icône à utiliser pour le marqueur, sa taille affichée (iconSize), sa position (iconAnchor) et le décalage de son ancrage (popupAnchor)
                    var myIcon = L.icon({
                        iconUrl: iconBase + "autres.png",
                        iconSize: [50, 50],
                        iconAnchor: [25, 50],
                        popupAnchor: [-3, -76],
                    });
                    var marker = L.marker([villes[ville].lat, villes[ville].lon], { icon: myIcon }); // pas de addTo(macarte), l'affichage sera géré par la bibliothèque des clusters
                    marker.bindPopup(ville);
                    markerClusters.addLayer(marker); // Nous ajoutons le marqueur aux groupes
                }
                macarte.addLayer(markerClusters);
            }
			window.onload = function(){
				// Fonction d'initialisation qui s'exécute lorsque le DOM est chargé
				initMap(); 
			};
		</script>
		<style type="text/css">
			#map{ /* la carte DOIT avoir une hauteur sinon elle n'apparaît pas */
				height:400px;
			}
		</style>
		<title>Carte</title>
	</head>
	<body>
		<div id="map">
			<!-- Ici s'affichera la carte -->
		</div>
	</body>
</html>

Adapter le zoom pour afficher tous les marqueurs

Il pourra être nécessaire, ponctuellement, d’adapter le zoom de la carte pour afficher automatiquement tous les marqueurs.

L’approche est simple, regrouper tous les marqueurs dans un tableau et demander à ce que le zoom s’adapte pour qu’ils soient tous visibles.

Voici le code de la fonction initMap finalisée

function initMap() {
	var markers = []; // Nous initialisons la liste des marqueurs
	// Nous définissons le dossier qui contiendra les marqueurs
	var iconBase = 'http://localhost/carte/icons/';
	// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
	macarte = L.map('map').setView([lat, lon], 11);
	markerClusters = L.markerClusterGroup(); // Nous initialisons les groupes de marqueurs
	// Leaflet ne récupère pas les cartes (tiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
	L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
		// Il est toujours bien de laisser le lien vers la source des données
		attribution: 'données © OpenStreetMap/ODbL - rendu OSM France',
		minZoom: 1,
		maxZoom: 20
	}).addTo(macarte);
	// Nous parcourons la liste des villes
	for (ville in villes) {
		// Nous définissons l'icône à utiliser pour le marqueur, sa taille affichée (iconSize), sa position (iconAnchor) et le décalage de son ancrage (popupAnchor)
		var myIcon = L.icon({
			iconUrl: iconBase + "autres.png",
			iconSize: [50, 50],
			iconAnchor: [25, 50],
			popupAnchor: [-3, -76],
		});
		var marker = L.marker([villes[ville].lat, villes[ville].lon], { icon: myIcon }); // pas de addTo(macarte), l'affichage sera géré par la bibliothèque des clusters
		marker.bindPopup(ville);
		markerClusters.addLayer(marker); // Nous ajoutons le marqueur aux groupes
		markers.push(marker); // Nous ajoutons le marqueur à la liste des marqueurs
	}
	var group = new L.featureGroup(markers); // Nous créons le groupe des marqueurs pour adapter le zoom
	macarte.fitBounds(group.getBounds().pad(0.5)); // Nous demandons à ce que tous les marqueurs soient visibles, et ajoutons un padding (pad(0.5)) pour que les marqueurs ne soient pas coupés
	macarte.addLayer(markerClusters);
}

Voilà, bon amusement

Commentaires

Ecrire un commentaire

polo a écrit le 11 janvier 2019 à 11:01

Bonjour

Je vous remercie pour tous ces conseils, cependant comme je connais pas JS

J'aimerais traitées dans la partie :: bulles d’informations

for (ville in villes) {
		var marker = L.marker([villes[ville].lat, villes[ville].lon]).addTo(macarte); 
	}  

marqueurs-> popup
1 - un petit txt HTML
2 - Liens HTML vers <a href='...'>

 

Encore merci

 

Répondre

DOM a écrit le 19 décembre 2018 à 09:12

Bonjour et merci pour cette très bonne explication.
Elle nous a permi d'initialiser notre développement.

Connaissez-vous des exemples avec une carte interactive ?
Je cherche surtout la possibilité d'ajouter un marker par l'utilisateur.
Leaflet a commercialisé un produit, mais :
1. Il est assez cher pour une intégration WordPress Multisites
2. Les APIs ont été modifiées il y a peu...
3. Je n'ai pas trouvé d'exemple à ce jour


Encore un grand merci pour cette précieuse aide !

 

 

Répondre

Nouvelle-Techno.fr a répondu le 19 décembre 2018 à 10:12

Bonjour,

Merci pour vos encouragements.

Je n'ai pas connaissance de ce produit de Leaflet.

Les ajouts de marqueurs par les utilisateurs, si ils sont enregistrés en base de données, peuvent se faire en Ajax.

Répondre

DOM a répondu le 20 décembre 2018 à 09:12

Effectivement le plugin est crll par MapsMarker et non Leaflet. Je les ai contacté au cas où ils ont dans leur planning la partie interactive.

Je contacterai aussi le dévelppeur  bozdoz du plugin https://fr.wordpress.org/plugins/leaflet-map/, peut-être a t-il pévu cela sous peu... Sinon, on effectuera le développement sous AJAX, mais j'ai l'impression de ré-inventer la roue.
Merci pour votre aide.

Répondre

Patrick a répondu le 20 décembre 2018 à 16:12

Jr'ai installé ce plug-in, en fait c'est la version de leaflet-easymap adapté à Wordpress, il permet de générer un code de la carte et de le coller dans le champ texte de la page, ce qui évite le JavaScript.

 

Répondre

DOM a répondu le 20 décembre 2018 à 17:12

Contact avec MapsMarker :

1. Leurs APIs (database API) qui permettraient de gérer les évènements ne sont pas encore documentées...
La page est vide:  https://www.mapsmarker.com/database-api
2. La date de sortie de la carte interactive (front end) est sur leur roadmap. Prévue pour Q2/Q3 2019.

 

Répondre

Patrick a écrit le 19 décembre 2018 à 08:12

Merci pour ce tuto,

Je vais utiliser OSM à la place de Google Maps dans lequel mes cartes se désactivent sans raison.
J'ai utilisé le plug-in Full Screen de Mapbox : https://www.ader-en-provence.fr/ader/boulbon-tarascon-barbentane-graveson-maillane-saint-etienne-du-gres/la-montagnette
Pour ce faire j'ai ajouté juste après

macarte = L.map('map').setView([lat, lon], 11);

le code

macarte.addControl(new L.Control.Fullscreen({
					title: {
						'false': 'Voir en mode plein écran',
						'true': 'Sortier du mode pleien écran'
					}
				}));

Il faut aussi intégrer le plug-in et son css entre les balises <head></head>

<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js'></script>
		<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css' rel='stylesheet' />

Je vais m'intéresser à l'intégration de polylignes.

Répondre

Nouvelle-Techno.fr a répondu le 19 décembre 2018 à 10:12

Merci pour votre commentaire.

Répondre

Gootime a écrit le 13 décembre 2018 à 11:12

Super tuto ! Merci a vous

Répondre

Nouvelle-Techno.fr a répondu le 13 décembre 2018 à 13:12

Merci à vous

Répondre

ACAB a écrit le 25 novembre 2018 à 09:11

Bonjour,

Merci pour ce tuto très clair. J'aurais cependant une question:

Comment insérer un tracé entre deux points sur la carte? Pour visualiser l'itinéraire?

Merci

Répondre

Patrick a répondu le 19 décembre 2018 à 10:12

Tu trouveras des explications ici https://leafletjs.com/reference-1.3.4.html#polyline-example
il faut intégrer le code suivant

var latlngs = [
    [45.51, -122.68],
    [37.77, -122.43],
    [34.04, -118.2]
];
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(macarte);

après la ligne

macarte = L.map('map').setView([lat, lon], 11);

Il y a aussi des plugins pour intégrer une trace gpx, soit en indiquant le fichier GPX, soit à partir d'une BD selon les besoins, voir tuto : https://dogeo.fr/importer-une-trace-gpx-dans-une-base-de-donnees-avec-leaflet-jsphp/
Pour ma part, j'ai créé la trace avec Josm sur un fond de carte Bing, je l'ai exportée en GPX (car l'export json interverti les coordonnées) puis je l'ai transformé au format Json manuellement avec Notepad++, voici le résultat :
https://www.ader-en-provence.fr/ader/boulbon-tarascon-barbentane-graveson-maillane-saint-etienne-du-gres/la-montagnette

Répondre

Xavier a écrit le 22 novembre 2018 à 21:11

Génial, 

après plusieurs recherches infructeuses, ce tuto m'éclaire !

Est-il possible d'ajouter des marqueurs à partir d'une base de données ?

Merci

Répondre

Nouvelle-Techno.fr a répondu le 22 novembre 2018 à 22:11

Bonjour,

Merci pour vos encouragements.

Il est tout à fait possible d'afficher les marqueurs à partir d'une base de données, les informations étant envoyées sous forme de tableau.

Les données viendront remplacer celles de la variable villes dans le code exemple.

Répondre

Patrick a répondu le 19 décembre 2018 à 08:12

Il faut remplacer ces lignes par un appel Ajax qui te retournera un fichier json depuis la BD :

// Nous initialisons une liste de marqueurs
            var villes = {
                "Paris": { "lat": 48.852969, "lon": 2.349903 },
                "Brest": { "lat": 48.383, "lon": -4.500 },
                "Quimper": { "lat": 48.000, "lon": -4.100 },
                "Bayonne": { "lat": 43.500, "lon": -1.467 }
            };

Tu trouveras la marche à suivre ici https://openclassrooms.com/courses/un-site-web-dynamique-avec-jquery/le-fonctionnement-de-ajax#/id/r-1572822

Répondre

Marc a écrit le 30 octobre 2018 à 16:10

Bonjour,

Merci pour ce tuto qui m'a permis de démarrer mon projet OpenStreetMap.

Pour allez plus loin, j'ai comme objectif de changer l'icon d'un marqueur sur une action externe à la carte (passage sur une div qui contient de l'info associée à ce marqueur). Pour cela je pensais utiliser la méthode "setIcon" de l'objet Marker, mais actuellemnt ça plante en me retournant dans la console le message d'erreur : " t.icon.createIcon is not a function " généré par le fichier leaftleft.js. Avez-vous une piste à ce sujet ?

Cordialment.
Marc

Répondre

Florent a écrit le 30 octobre 2018 à 11:10

Bonjour,

Merci pour le tuto très clair.

Peut-on changer le Layer (style de carte) ?

Merci

Répondre

Florent a répondu le 31 octobre 2018 à 15:10

Merci beaucoup !

Répondre

Marcus a écrit le 19 octobre 2018 à 00:10

Wow!!! Vous n'imaginez même pas l'aide que vous venez de m'apporter !

Merci infiniment.......

Répondre

Nouvelle-Techno.fr a répondu le 19 octobre 2018 à 07:10

Merci à vous.

Répondre

Amiral a écrit le 11 octobre 2018 à 18:10

Excellent article, très complet et explicite.

Répondre

Nouvelle-Techno.fr a répondu le 11 octobre 2018 à 21:10

Merci beaucoup Amiral

Répondre

Laisser un commentaire