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

11 mai 2018 - : HTML Javascript Tutoriel - : 90 commentaires - Tutoriel Javascript Openstreetmap

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="" />
        <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>

        <!-- Fichiers Javascript -->
        <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>
    </body>
</html>

Ajout d’un marqueur

Voir cette partie en vidéo

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

Voir cette partie en vidéo

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

Voir cette partie en vidéo

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

Voir cette partie en vidéo

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" />
        <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>

        <!-- Fichiers Javascript -->
        <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>
    </body>
</html>

Adapter le zoom pour afficher tous les marqueurs

Voir cette partie en vidéo

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

Obtenir de l'aide

Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat

Partager

Partager sur Facebook Partager sur Twitter Partager sur LinkedIn

Commentaires

Ecrire un commentaire

salem blg a écrit le 9 juillet 2020 à 15:00

Bonjour j ai besoin d intégrer votre travail dans ma application jee s'il vous plait pouvez vous me guider merci

Répondre

koukou a écrit le 14 mai 2020 à 13:14

Merci pour ce tuto!!

J'ai beaucoup de marqueurs à chargé dans le map, tout ca marche bien mais le rafraîchissement intempestif de la carto bloque la page car les marqueurs se refraichit de nouveau dans la carte pourtant il n'y a pas de nouveaux donnés, les données sont bien chargés dans une liste et j'ai parcourit la liste pour construire les marqueurs.

Répondre

Ok-Google a écrit le 12 mai 2020 à 11:04

Bonjour, serait-il possible de savoir comment relier les marqueurs entre eux ?

Répondre

lexa1234 a répondu le 27 juin 2020 à 13:06

Pour relier 2 marqueurs entre eux, cela revient selon moi à créer un itinéraire, et donc à utiliser une service de rooting. Il faut utiliser une autre librairie.

Répondre

unzarida a écrit le 1 mai 2020 à 08:40

Bonjour,

Je vous remercie pour ce tuto très clair ! Je l'ai mis sur un site web sans problème, par contre pour la version mobile, la carte ne s'affiche pas, elle apparaît en gris. Savez-vous pourquoi ?

En vous remerciant

Répondre

Laurent 84 a écrit le 30 avril 2020 à 18:37

Bonjour,

après avoir passé en revue pas mal de services payants (Mapbox, Geoapify, MapQuest), un peu calqués sur la tarification Google, je trouve presque trop beau de pouvoir bénéficier de cartes sans aucune inscription à un service !

Connaissez-vous les limitations commerciales et techniques à appeler un serveur comme tile.openstreetmap.fr ?

Merci en tout cas pour votre tuto !

 

Répondre

Awaz a répondu le 9 juillet 2020 à 16:47

Salut,

Il n'y a pas de limitation, OpenStreetMap est collaboratif et gratuit. L'utilisation de l'API Leaflet est aussi gratuite. D'ailleur beaucoup de site de gouv.fr l'utilisent. Je l'utilise depuis un certain temps, tant en statique (avec Python) qu'en dynamyque avec PHP sans aucun problème. Je n'ai pas des milliers de connections sur mon site, mais je devrai payer 7$/mois à Google si j'utilisais leur API alors qu'avec OSM et Leaflet, rien... D'ailleurs, il n'y a aucune inscription ou clef à renseigner dans votre projet.

Cordialement

Awaz

Répondre

Yan a écrit le 22 avril 2020 à 09:42

Un grand merci !

Répondre

Rayman a écrit le 14 avril 2020 à 21:42

Formidable, enfin trouvé comment intégrer la map sans passer par l'iframe fourni par umap ! Merci :D

Par contre, comment dessiner des lignes et polygones ? Ici le tuto ne mentionne que des points.

Répondre

w a écrit le 1 avril 2020 à 23:00

salut, tout d'abord je veux remercier pour la video et pour tes efforts, merci inffiniment,

j'ai un problèle à propos l'importation des poins sur la carte, coté console m'affiche une erreur,

[ index.html:53 Access to XMLHttpRequest at 'file:///C:/wamp/www/PFE/mourad/tuto_fr/liste.php' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. ]

Répondre

Nouvelle-Techno.fr a répondu le 2 avril 2020 à 16:38

Bonjour,

Une requête Ajax ne peut pas se faire vers un fichier local, il faut une URL complète commençant par https.

Répondre

alizee_w a écrit le 21 février 2020 à 10:59

Bonjour,

est-ce possible de choissir ce qu'on veut afficher sur la carte? Par exemple je ne voudrais pas tous les magasins, restaurants, juste les monuments. C'est possible? Si oui comment est ce que je peux faire ?

Merci d'avance,

Répondre

jm a écrit le 13 février 2020 à 20:02

Bonjour,

Super tuto merci beaucoup.

J'ai une petite question, j'ai utilisé les clusters, j'ai rajouté une donnée dans le tableau des poi (ici "t" qui peut être egale a "0,1,2,3,4"). j'aimerais que l'icone de mon marqueur cluster soit l'icone qui correspond a la variable t la plus présente dans le cluster (et non pas le rond vert avec le chiffre) ... est-ce possible svp?

Merci beaucoup.

Répondre

Nouvelle-Techno.fr a répondu le 13 février 2020 à 20:56

Bonsoir,
Je ne pense pas que ce soit prévu dans cette bibliothèque.

Répondre

Ecrire un commentaire