3.6. Les données vectorielles dans Leaflet

Dans ce chapitre, nous allons voir comment afficher des données issues d'un fichier GeoJSON sur une carte Leaflet. Nous verrons également comment attribuer des couleurs aux entités GeoJSON en fonction d'un attribut.

3.6.1 Le format GeoJSON

Le format GeoJSON est la variante "spatiale" du format de données JSON, dont la particularité est d'être inspiré par la syntaxe des objets en JavaScript. C'est donc un format idéal pour le webmapping !

Exercice 4. Ouvrez dans un éditeur de texte le fichier data/webmapping/3_leaflet/data/point_legend_1724.json pour visualiser la structure du fichier avec les indentations. Copiez le contenu du fichier dans le presse-papier.

Ouvrez la console JavaScript de Firefox (touche <F12>) et tapez : "var datageo = ", suivi du contenu du fichier GeoJSON (collez le contenu), suivi de <Entrée>.

Puis, toujours dans la console, tapez :

datageo.features[0].properties.libelle
datageo.features[1].geometry.coordinates

Quelle commande JavaScript permettrait de définir une nouvelle variable test_lat avec la latitude de la 3ème entité du fichier GeoJSON ?

Voir la solution

3.6.2. Charger une couche GeoJSON dans Leaflet

Pour charger sur une carte un objet GeoJSON, Leaflet propose la syntaxe suivante :

L.geoJSON(datageo).addTo(ma_carte);

Les géométries issues du GeoJSON doivent être dans le système de coordonnées WGS84 (EPSG:4326). Un fichier GeoJSON peut contenir des points, des lignes, des polygones voire un mélange de tout cela. Dans le cas de points, les entités apparaîtront sous forme de marqueurs.

Pour en savoir plus, consulter l'exemple dans la documentation de Leaflet : https://leafletjs.com/examples/geojson/

Ajax pour charger un fichier (ou un web service) GeoJSON

Pour charger les données issues d'un fichier GeoJSON dans une page, nous avons besoin de recourir à la technique de programmation asynchrone Ajax. De quoi s'agit-il ?

schema Ajax

  • une requête http est associée à une fonction de callback
  • la requête http consiste à charger une ressource (autrement dit des données), avec un URL. Exemple : http://localhost/3_leaflet/data/point_legend_1724.geojson
  • quand les données sont entièrement chargées, la fonction de callback est exécutée. Exemple : une fonction qui affiche les données sur la carte avec L.geoJSON.

Pour mettre en oeuvre le chargement d'un fichier JSON, nous pouvons utiliser la fonction getJSON de l'API jQuery. Dans l'entête de la page HTML, nous ajoutons une référence à l'API :

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Dans le code, après avoir créer l'objet Map de Leaflet, on peut alors utiliser la fonction getJSON avec un URL (chaîne de caractères) et une fonction à appeler.

$.getJSON(url_data, function(data) {
    L.geoJson(data).addTo(ma_carte);
});

TP Plan de Montpellier en 1724 (1/3)

Dans Visual Studio Code, ouvrez le fichier modele_leaflet.html et enregistrez une copie sous le nom tp_montp1724.html. La page affiche une carte Leaflet centrée sur Montpellier.

Ouvrez la page dans le navigateur : http://localhost/3_leaflet/tp_montp1724.html

Dans l'entête de la page, changez le titre :

<title>Plan de Montpellier</title>

Ajoutez une référence à l'API jQuery :

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Dans le corps de la page, changez le contenu de la page :

<h4>Plan de la ville et citadelle de Montpellier, 1724</h4>
<p>Ce  plan à l’échelle du 1/3600, avec voies et édifices principaux 
repérés par des numéros renvoyant à la légende, a été réalisé à l’encre 
et aquarelle en 1724. Il est signé d’Antoine Niquet, directeur des 
fortifications de Provence et du Languedoc, et directeur des travaux 
publics du Languedoc. Il encadre trois projets d’aménagement urbain 
impliquant directement cet ingénieur militaire.</p>

Dans le code JavaScript, vous allez ajouter une couche avec le plan de Montpellier en 1724. Utilisez les tuiles générées dans la partie 3.4 dans le répertoire ~/data/mon_travail/3_leaflet/tiles/M1724.

// ajout tuiles Montpellier 1724 (localhost)
L.tileLayer('http://localhost/3_leaflet/tiles/M1724/{z}/{x}/{y}.png', {
    tms: true, opacity: 0.8, attribution: "", minZoom: 14, maxZoom: 18
}).addTo(ma_carte);

Enregistrez le fichier HTML et rechargez la page dans le navigateur.

Vous allez maintenant charger les données GeoJSON des lieux remarquables (points), et de l'occupation du sol (polygones). Utilisez getJSON avec une fonction de callback qui ajoute la donnée à la carte.

var url_points = "http://localhost/3_leaflet/data/point_legend_1724.geojson"
var url_occsol = "http://localhost/3_leaflet/data/occsol_1724.geojson"
$.getJSON(url_points, function(data){
    L.geoJson(data).addTo(ma_carte);
});
$.getJSON(url_occsol, function(data){
    L.geoJson(data).addTo(ma_carte);
});

Enregistrez le fichier HTML et rechargez la page dans le navigateur.

Associer des popup aux entités

Si vous souhaitez associer des popups aux entités du fichier GeoJSON, vous devez définir pour cela une fonction qui associe un message à l'entité, puis appliquer cette fonction à chaque entité.

Pas besoin de boucler sur les entités cependant, il existe un moyen de leur appliquer directement la fonction : l'option onEachFeature, dans la classe geoJson. Voir un exemple dans le TP ci-dessous.

Copie écran GeoJSON

TP Plan de Montpellier en 1724 (2/3)

Vous allez modifier la couche des points remarquables, de manière à ce qu'un clic sur un marqueur affiche le numéro et le libellé du point.

Tout d'abord, définissez une fonction JavaScript qui associe aux marqueurs une popup avec le numéro et le libellé :

function associerPopup(feature, marker) {
    var popup_message = "<strong>" + feature.properties.numero + "</strong>. " + feature.properties.libelle;
    marker.bindPopup(popup_message);
}

Remarquez les 2 paramètres de cette fonction "maison" : l'entité (feature) et le marqueur (marker).

Il faut appeler cette fonction associerPopup pour chaque entité des données GeoJSON. Modifiez l'appel à la fonction L.geoJson qui ajoute les marqueurs à la carte :

$.getJSON(url_points, function(data){
    L.geoJson(data, {
        onEachFeature: associerPopup
    }).addTo(ma_carte);
});

Enregistrez et rechargez la page dans le navigateur.

Changer le style des entités

Dernière étape de notre chapitre sur les données vectorielles : nous allons modifier l'aspect des polygones Occupation du sol issus des données GeoJSON. Le but est d'associer des couleurs aux différents types d'occupation du sol (propriétés libelle).

Copie écran GeoJSON

La fonction geoJson dispose d'une option style pour associer aux entités des propriétés graphiques différentes du bleu proposé par défaut.

Vous pouvez passez à cette option style :

  • soit un objet, avec les propriétés graphiques définies ici
  • soit une fonction

TP Plan de Montpellier en 1724 (3/3)

1ère étape : affichez les polygones d'occupation du sol avec un contour gris sombre et un remplissage jaune.

var symbole_unique = {
    color: "#232323",
    fillColor: "#d9e278",
    weight: 1,
    fillOpacity: 0.8
};

$.getJSON(url_occsol, function(data){
    L.geoJson(data, {
        style: symbole_unique
    }).addTo(ma_carte);
});

Enregistrez et rechargez la page dans le navigateur.

2nde étape : remplacez le symbole unique par une couleur associée à chaque type d'occupation du sol. Voici un tableau des couleurs à associer aux libellés.

valeur libelle couleur remplissage
bâti #ea6e7f
culture #d9e278
friche #eebc46
vigne #ac7aec
potager #22da12
autres #1687ea

Vous devez définir une fonction qui renvoie un symbole avec une couleur de remplissage différente selon la propriété libelle, et associer cette fonction à l'option style :

function definirStyle(feature) {
    var prop_graph = { color: "#232323", weight: 1, fillOpacity: 0.8 };
    switch (feature.properties.libelle) {
        case 'bâti': prop_graph.fillColor = "#ea6e7f"; break;
        case 'culture': prop_graph.fillColor = "#d9e278"; break;
        case 'friche': prop_graph.fillColor = "#eebc46"; break;
        case 'vigne': prop_graph.fillColor = "#ac7aec"; break;
        case 'potager': prop_graph.fillColor = "#22da12"; break;
        default: prop_graph.fillColor = "#1687ea";
    }
    return prop_graph;
}

$.getJSON(url_occsol, function(data){
    L.geoJson(data, {
        style: definirStyle
    }).addTo(ma_carte);
});

Comment cela fonctionne t-il ?

Notre fonction definirStyle renvoie un objet prop_graph différent selon le paramètre feature (l'entité en entrée). Ce qui ne change pas : l'objet prop_graph renvoyé a toujours la même couleur de contour (color) avec la même épaisseur (weight), et la même opacité de remplissage (fillOpacity). Ce qui change : la couleur de remplissage (fillColor), selon la propriété libelle de l'entité.

Cette fonction definirStyle est appliquée à chaque entité de la couche geoJson qui est ajoutée à la carte dans la foulée.

3.6.3. A RETENIR

  • Le format GeoJSON est un format de données vectorielles spécialement adapté au web. Il se manipule aisément en Javascript.
  • Les ressources disponibles sous forme de fichier, GeoJSON ou autre, peuvent mettre un temps variable à transiter sur le réseau et il n'est pas question de suspendre l'exécution d'un script en attendant leur chargement. C'est pourquoi en Javascript on utilise une technique de programmation asynchrone appelée Ajax : on définit une fonction qui sera exécutée quand le fichier GeoJSON sera complètement chargé.
  • Le webmapping repose grandement sur la programmation asynchrone.
  • Dans Leaflet, l'aspect des données vectorielles est défini par le biais d'objets (avec des propriétés telles que color, fillColor, weight, fillOpacity) passés en option lors de l'ajout des couches.