Chibi-nah::blog

Des geekeries, de la MAO, de tout et de rien…

Archives

Affichage de points sur une carte

Un petit article pour ceux qui veulent utiliser un fond de carte OpenStreetMap et ajouter des informations au dessus, avec la librairie javascript leaflet

Note : je m'étais inspiré de ce tutoriel pour écrire le script mi 2015 en octobre 2015, pour des besoins propres. Pour la rédaction de cet article, je suis reparti du script et non du tutoriel.

Note 2 : cet article ne couvre qu'une toute petite partie de ce que l'on peut faire avec leaflet. On peut en plus tracer des polygones sur la carte, tracer un cercle autour d'un point…

Un petit exemple :

Carte de la ville de Paris, dans OpenStreetMap, avec un point rouge au niveau de la tour Eiffel et une description et photo de ce monument

Comment faire ?

Il faut deux choses :

  • des données ;
  • du temps.

Commençons par les données.

Il faut à minima :

  • Les coordonnées des points à afficher
  • Un texte à afficher

Exemple simple

Prenons le cas de la Tour Eiffel. Elle se trouve aux coordonnées suivantes : latitude 48.8582, longitude 2.2945. Utilisons donc le nom « Tour Eiffel ».

Les données seront stockées au format json. Pour cet exemple, le fichier json est présent sous la forme d'un fichier texte et non généré automatiquement à partir de données stockées dans une base de données.

Contenu du fichier js données :

markers = [
    {
        "name": "Tour Eiffel",
        "lat": 48.8582,
        "lng": 2.2945
    }
];

Peu d'explications sont nécessaires : j'utilise trois champs : name, qui contient le nom (ou le titre, peu importe le nom), lat, contient la latitude, et lng, la longitude. Le tout est stocké dans un array (tableau, d'où les []) nommé markers.

On a (pour le moment) une donnée. Maintenant, il faut l'afficher sur la carte. Pour cela, il faut inclure dans la page html :

  • Le script js et la css de leaflet, à inclure dans l'entête de la page html (section head)
  • Le script js de jquery, à inclure dans l'entête de la page html (section head).
  • Le script d'initialisation et de traitement/formatage des données pour leaflet. (détaillé plus bas).
  • Le fichier json contenant les données.

Éléments à inclure dans la page :

<head>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.css" />
<script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js?2"></script></head>
<body><div id="map" style="height: 800px; border: 1px solid #AAA;"></div>
<script type='text/javascript' src='images/map/markers.json'></script>
<script type='text/javascript' src='images/map/leafScript.js'></script>

Remarque : Autant cela fonctionnait en 2015, autant cela ne fonctionne plus en 2021 (erreurs de certificat). Héberger jquery et leaflet (js et css) en local pour limiter ce genre de problème.

Passons maintenant au script qui va initialiser leaflet et formater les données.

Contenu du script :

//Initialisation des coordonnées de la map. Ici, au dessus de Paris
var map = L.map( 'map', {
    center: [48.8662, 2.3124],
    minZoom: 2,
    zoom: 14
});

//Chargement des tuiles
// Consulter cette page pour la liste des serveurs : http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_servers
//
//mapquest : http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png
//OSM : http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png

L.tileLayer( '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '(C) <a href="http://osm.org/copyright" title="OpenStreetMap" target="_blank">OpenStreetMap</a> contributors | Demo by <a href="http://nah.re" target="_blank" tilte="nah">nah</a>',
    subdomains: ['a','b','c']
}).addTo( map );


//Gestion des popups. On boucle sur les données contenues dans le fichier json
for ( var i=0; i < markers.length; ++i )
{
    L.marker([markers[i].lat, markers[i].lng],{})
        .bindPopup('<b>' + markers[i].name + '</b>')
        .addTo( map );
}

Voilà. On a maintenant un marqueur bleu au dessus de la Tour Eiffel, sur la carte, ainsi qu'un popup qui est affiché lorsque l'on clique sur le marqueur.

Cet exemple, avec le code minimaliste (et non minifié) est visible ici :

demo-bleu.html

Second exemple

Maintenant, allons plus loin. Je veux afficher la Tour Eiffel, la Pyramide du Louvre et l'arc de triomphe sur une carte, avec des pointeurs rouges, une infobulle qui affiche une photo et un résumé provenant de wikipédia ainsi qu'un lien vers l'article de ce dernier.

Modifions le fichier de données comme suit :

Contenu du fichier js données :

markers = [
    {
        "name": "Pyramide du Louvre",
        "comments": "La pyramide du Louvre est une pyramide constituée de verre et de métal, située au milieu de la cour Napoléon du musée du Louvre à Paris, où se situe le hall d’accueil.",
        "wikipedia":"http://fr.wikipedia.org/wiki/Pyramide_du_Louvre",
        "lat": 48.86102,
        "lng": 2.33582,
        "photo_uri": "https://commons.wikimedia.org/wiki/File%3ALouvre_Pyramid_-_censored_copyright_2.jpg",
        "photo_thumbnail": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Louvre_Pyramid_-_censored_copyright_2.jpg/128px-Louvre_Pyramid_-_censored_copyright_2.jpg",
        "attribution": "Par hakkun, Zscout370 [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons"
    },
    {
        "name": "Tour Eiffel",
        "comments": "La tour Eiffel est une tour de fer puddlé de 324 mètres de hauteur située à Paris, à l’extrémité nord-ouest du parc du Champ-de-Mars en bordure de la Seine dans le 7ᵉ arrondissement.",
        "wikipedia":"http://fr.wikipedia.org/wiki/Tour_Eiffel",
        "lat": 48.8582,
        "lng": 2.2945,
        "photo_uri": "https://commons.wikimedia.org/wiki/File%3AEiffelturm.JPG",
        "photo_thumbnail": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Eiffelturm.JPG/128px-Eiffelturm.JPG",
        "attribution": "Par Benutzer:BigBartimäus (Photographie personnelle) [Public domain], via Wikimedia Commons"
    },
    {
        "name": "L'arc de triomphe",
        "comments": "L’arc de triomphe de l’Étoile souvent appelé simplement l'Arc de Triomphe, dont la construction, décidée par l'empereur Napoléon Iᵉʳ, débuta en 1806 et s'acheva en 1836 sous Louis-Philippe, est situé à Paris, dans le 8ᵉ arrondissement.",
        "wikipedia":"http://fr.wikipedia.org/wiki/Arc_de_triomphe_de_l%27%C3%89toile",
        "lat": 48.87376,
        "lng": 2.29504,
        "photo_uri": "https://commons.wikimedia.org/wiki/File%3AParis_Arc_de_Triomphe_011.jpg",
        "photo_thumbnail": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Paris_Arc_de_Triomphe_011.jpg/128px-Paris_Arc_de_Triomphe_011.jpg",
        "attribution": "By Vassil (Own work) [Public domain], via Wikimedia Commons"
    }
]

J'ai ajouté quelques éléments en plus, notamment les commentaires (ou description), les liens vers les photos/vignettes, et bien entendu, les attributions pour les auteurs des photos.

À noter : on a un truc absurde en France, au niveau du droit d'auteur. La liberté de panorama n'est pas autorisée. On n'a pas le droit de publier une photo d'une sculpture/monument/œuvre d'art exposée dans rue, sans demander l'autorisation aux ayants droits. Pour la Tour Eiffel (de jour, uniquement, de nuit, l'éclairage est sous droits d'auteur) et l'arc de triomphe, il n'y a pas de problème, les 70 ans après la mort du créateur/auteur/architecte sont largement dépassés. Pour la pyramide du Louvre, datant du début des années 1990, ce n'est pas le cas. Du coup, la photo de la pyramide est censurée.

Plus d'infos sur cette absurdité : https://commons.wikimedia.org/wiki/Commons:Freedom_of_panorama/fr#France

Et le script comme suit :

Contenu du script :

//Initialisation des coordonnées de la map
var map = L.map( 'map', {
    center: [48.8662, 2.3124],
    minZoom: 2,
    zoom: 14
});

//Initialisation de l'icône du marqueur
var redIcon = L.icon({
    iconUrl: 'images/map/marker-icon-red.png',
    iconSize: [25,41]
});


//Chargement des tuiles
// Consulter cette page pour la liste des serveurs : http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_servers
//
//mapquest : http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png
//OSM : http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png

L.tileLayer( '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '(C) <a href="http://osm.org/copyright" title="OpenStreetMap" target="_blank">OpenStreetMap</a> contributors | Demo by <a href="http://nah.re" target="_blank" tilte="nah">nah</a>',
    subdomains: ['a','b','c']
}).addTo( map );


//Gestion des popups.
for ( var i=0; i < markers.length; ++i )
{
    L.marker([markers[i].lat, markers[i].lng],
    {
        icon: redIcon
    })
        .bindPopup('<a title="' + markers[i].attribution + '" href="' + markers[i].photo_uri + '"><img src="' + markers[i].photo_thumbnail + '" /></a><br /><b>' + markers[i].name + '</b><br /><i>' +  markers[i].comments + "</i><br /><a href='" + markers[i].wikipedia + "'>Wikipédia</a>")
        .addTo( map );

}

Les modifications du script sont « simples ». On ajoute l'icône rouge et le traitement des infos (+formatage) dans l'info-bulle et le tour est joué.

Le résultat des modifications est visible en haut de cette page. C'est le code qui est utilisé pour afficher la carte de l'exemple.

Cet exemple, avec le code minimaliste (et non minifié) est visible ici :

demo.html

Il y aurait encore pas mal de choses à expliquer sur les fonctionnalités de leaflet, notamment sur le tracé de polygones, pour entourer un parking, par exemple, mais je vais m'arrêter là.

Liens

Leaflet : http://leafletjs.com/ Source des données : Script :

Le script leafScript.js et le fichier de données markers.json sont sous licence WTFPL version 2.