Skip to Content

Leaflet la simple [3] Carte Choroplèthe

Niveau Débutant
Logiciels utilisés Leaflet
Plateforme Windows | Mac | Linux

Aujourd’hui nous allons voir comment créer une carte choroplèthe interactive. Dans la continuité du dernier article, nous utiliserons à nouveaux des données sur le bio en France. L’objectif du jour est de représenter la part de SAU (Surface Agricole Utile) bio par région. Nous reprendrons certains aspects du précédent article et découvriront comment :

  • Définir le style d’un Geojson surfacique en fonction d’un attribut
  • Changer le style d’un élément à son survol ou lors d’un clic.

1) Données de base 

Un Geojson contenu dans un fichier JavaScript :

  • Geojson « Region » : BD GEOFLA aux contours simplifiés sur GrassGIS avec un champ représentant la part de la SAU bio.

Le fichier Js est disponible en fin du tutoriel précedent (www.portailsig.org/content/leaflet-la-simple-2-cercles-proportionnels), mais vous pouvez tout à fait utiliser vos propres données.

2) Tutoriel

Pour commencer, nous allons repartir des fichiers HTML et JavaScript créés durant le premier article. Je passerai rapidement sur les concepts déjà évoqués durant l’article précédent.

a) Lien vers les données

La première étape consiste à lier les données au script HTML : 

<script src="lien/vers/les/donnees.js"></script>

b) Création de la couche région.

var regionGeoJs=L.geoJson(region).addTo(map);

"region" correspond à la variable contenant le geojson définie dans le fichier des données.

c) Définition du style de la couche région

Pour définir le style de la couche region, nous allons utiliser deux fonctions. La première permet de définir le style générale de la couche. La seconde permet de définir la couleur de la région en fonction du pourcentage de terre en agriculture biologique. Ces deux fonctions s'écrivent en dehors de la fonction principale init(). L'appel de la seconde fonction se fait dans la première.

function styleReg(feature){
  return{
    fillColor: getColor(feature.properties.SAU_AB),
    weight: 2,
    opacity: 1,
    color: 'white',
    fillOpacity: 0.7
  };
}

La fonction getColor() est lancée avec comme paramètre la valeur de l'attribut SAU_AB. En fonction de la valeur de cet attribut, une couleur sera définie pour la région. 

function getColor(a){
  return  a>8.5 ? '#006D2C':   
          a>5   ? '#31A354':
          a>2.8 ? '#74C476':
          a>1.5 ? '#A1D99B':
                  '#C7E9C0'; }

Une fois ces deux fonctions définies, il faut ajouter l'appel à la première fonction dans la fonction init():

var regionGeoJs=L.geoJson(region,{style:styleReg}).addTo(map);

Voilà le résultat à ce stade :

Carte intermédiaire

d) Définition des actions liées à la souris

La gestion des évenements liés à la souris (clic et survol) se fait via un attribut "onEachFeature" dans le dictionnaire envoyé à la fonction L.geojson. Notre appel de la fonction devient donc :

var regionGeoJs=L.geoJson(region,{
  style : styleReg,
  onEachFeature : evenement
  }).addTo(map);

Où evenement() est une fonction définissant les changements à opérer après une action de la souris. 

Nous allons maintenant créer la fonction evenement().

function evenement(feature, layer) {
  layer.on({
    mouseover: highlightFeature,
    mouseout: resetHighlight,
    click: zoomToFeature
    });
  }

Une fois de plus, cette fonction fait appel à d'autre fonctions : highlightFeature() pour la mise en valeur de l'entité survolée par la souris, resetHighlight() pour supprimer cette mise en valeur et zoomToFeature() pour zoomer sur l'entité cliquée.

function highlightFeature(e) {
  var layer = e.target;

  layer.setStyle({
    weight: 3,
    color: '#666',
    dashArray: '',
    fillOpacity: 0.7
  });

  if (!L.Browser.ie && !L.Browser.opera) {
    layer.bringToFront();
  }
}

Cette fonction permet de modifier le style de l'entité survolée. La modification restera effective si on ne créé pas une autre fonction qui rétablie le style de départ. C'est le rôle de la fonction resetHighlight().

function resetHighlight(e) {
  regionGeoJs.resetStyle(e.target);
}

Attention : Ici nous utilisons la variable "regionGeoJs", or cette variable est pour l'instant créée dans la fonction init() et n'est donc accessible que par celle-ci : c'est une variable locale à la fonction init(). Il faut donc créer la variable en dehors des fonctions pour qu'elle devienne variable globale. (Pour plus d'info sur le sujet : portée des variables sur Google). En tête de fichier javascript rajouter :

var regionGeoJs;

et dans la fonction init() il suffit de supprimer le "var" devant regionGeoJs:

regionGeoJs=L.geoJson(...).addTo(map);

Enfin, on veut qu'après un clic, l'affichage soit modifié pour afficher la région en question.

function zoomToFeature(e) {
  map.fitBounds(e.target.getBounds());
}

Comme pour la variable "régionGeoJs", la variable map doit être déclarée en dehors de la fonction init().

Nous avons maintenant des entités qui réagissent en fonction de la souris de l'utilisateur.

e) Ajout d'un titre et d'information sur la région survolée par la souris

Pour rajouter de l'intéractivité et pour plus de précision, nous allons rajouter des informations sur la région survolée par la souris. Voilà la procédure à suivre pour obtenir ce résultat. On revient au sein de la fonction init() :

 info = L.control();

 info.onAdd = function (map) {
   this._div = L.DomUtil.create('div', 'info'); 
   this.update();
   return this._div;
 };

info.update = function (props) {
  this._div.innerHTML = '<h4>Part de la SAU en Agriculture Biologique</h4>' +  (props ?
    '<b>' + props.NOM_REGION + '</b><br />' + props.SAU_AB + ' %'
    : 'Passez la souris sur une région<br>');
};

info.addTo(map);

L'information est donc stockée dans un "control" dans lequel on créé une balise div info. Dans la seconde partie, pour les non spécialistes de javascript (comme moi), l'expression entre paranthèses (props?'<b>[...]<br>') est une condition :

(condition ? expr1 : expr2) se lit "Si condition est vraie alors expr1 est éxécutée sinon expr2 est éxécutée"

Nous avons donc définit ce que notre controle doit afficher. Si on fait le test dès maintenant et que l'on survole une région avec la souris... et bien rien. Il nous reste en effet à définir dans les fonctions highlightFeature() et resetHighlight() que notre div info doit être mise à jour. On rajoute donc dans ces fonctions :

function highlightFeature(e) {
  ...
  info.update(layer.feature.properties);
}


function resetHighlight(e) {
  ... 
  info.update();
}

Pour une mise en page plus sympa voir le fichier css définit dans l'article précédent (www.portailsig.org/content/leaflet-la-simple-2-cercles-proportionnels)

f ) La légende

Nous allons voir ici comment générer automatiquement la légende en javascript.

var legend = L.control({position: 'bottomleft'});

  legend.onAdd = function (map) {
    var div = L.DomUtil.create('div', 'info legend'), //Création d'une balise div
      seuils = [0, 1.5, 2.8, 5, 8.5], //Definition des seuils
      labels = [];
      div.innerHTML +="Part de la SAU en<br>agriculture biologique<br>"; //Titre
    // Boucle sur les seuils établis et création d'une etiquette et d'un carré de couleur.
    for (var i = 0; i < seuils.length; i++) {
      div.innerHTML +=
        '<i style="background:' + getColor(seuils[i]+1) + '"></i> ]' +
        seuils[i] + (seuils[i + 1] ? ' &ndash; ' + seuils[i + 1] + '] %<br>' : ' + %');
    }

    return div;
};
legend.addTo(map);

Pour avoir un affichage correct, il faut completer le fichier style.css avec le code suivant.

.legend {
  line-height: 18px;
  color: #555;
}
.legend i {
  width: 18px;
  height: 18px;
  float: left;
  margin-right: 8px;
  opacity: 0.7;
}

Voilà pour ce tutoriel sur la réalisation d'une carte choroplèthe avec Leaflet. Le résultat est visible ici : dl.dropboxusercontent.com/u/158393558/PortailSIG/CP.html 

 

Dans le prochain article nous verrons quelques exemples de plugins intéressants de Leaflet.

Site officiel : leaflet
Autres Liens : Leaflet la simple[1]
Autres Liens : Leaflet la simple[2]

Commentaires

Poster un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.