Accueil / Blog / Métier / 2015 / Elections.js génère des cartes pour vous

Elections.js génère des cartes pour vous

Par Simon Georges publié 30/03/2015
Le travail sur les cartes pour les élections départementales a débouché sur la création d'un outil générique : elections.js.
Elections.js génère des cartes pour vous

Carte des résultats à Toulouse

Les cartes que nous avons réalisées pour les élections départementales 2015 ne nécessitent pas une expertise trop poussée de LeafletJS, mais elles ont tout de même constitué une occasion de mettre au point quelques techniques permettant de réutiliser un même javascript dans des contextes différents, afin d'assurer à l'avenir une réalisation de cartes de résultats d'élections très rapide.

Introduction

Une carte présentant des résultats électoraux est composée d'essentiellement 2 choses : une information géographique délimitant la zone concernée, et une présentation colorée des résultats. Mais pour assurer une ré-utilisabilité maximum, nous nous devons de prendre en compte un maximum de possibilités ou de formats de données.

Une fois les parties "métier" (calcul du résultats, informations textuelles de la légende) exportées dans un fichier de paramètres externe, nous nous retrouvons avec un fichier elections.js qui se concentre sur la cartographie, et peut gérer une palette de cas différents.

Des géométries variées

La plupart des grandes plateformes Open Data françaises diffusent la géographie de leur bureau de vote par "zone", et donc en polygones. C'est aussi la géométrie que nous préférons car c'est celle qui permet la visualisation la plus immédiatement compréhensible, puisque la plus habituelle. C'est donc notre géométrie de prédilection dans le script :

Cependant, la plupart des mairies qui diffusent (comme le veut la loi) la répartition des bureaux de vote le font en indiquant le nom des rues. Cela nous permet alors, en dessinant manuellement ces rues par exemple, de générer un fichier geojson de ces bureaux de vote composé de plusieurs lignes pour un bureau de vote. Pour prendre en compte ce type de représentation dans le script, il nous a suffit de modifier la façon de styler le geojson dans le cas de cette géométrie particulière. Le style étant appliqué sur chaque feature, par la fonction onEachFeature(), il nous suffit, dans cette fonction où d'habitude on style un polygone, de modifier le style utilisé pour l'adapter aux lignes :

if (feature.geometry.type == 'MultiLineString') {
 layer.setStyle({color: couleur, weight: 4, opacity: 1});
}

En affectant le poids et l'opacité de la zone, le résultat est certes différent des polygones, mais la coloration politique de chaque zone est immédiatement reconnaissable également :

Enfin, d'autres plateformes fournissent les bureaux de vote en indiquant uniquement l'adresse du bureau de vote, nous amenant alors à ruser un peu : dans la mesure où ce qui nous intéresse est de styler automatiquement la zone d'après la couleur du parti, nous utilisons une fonctionnalité de Leaflet permettant d'utiliser des cercles SVG à la place des marqueurs de point par défaut. Cette fonctionnalité est réalisable grâce à une fonction pointToLayer() passée en paramètre à la construction du GeoJSON. Par chance, cette fonction n'affecte pas les géométries lignes ou polygones, nous pouvons donc la laisser en permanence, elle ne s'appliquera qu'en cas de besoin :

$.getJSON('contours.geojson', function(data) {
  var layer = L.geoJson(data, {
    onEachFeature: onEachFeature, // fonction citée précédemment
    pointToLayer: function (feature, latlng) {
      return L.circleMarker(latlng);
    }
});
});

Grâce à cette astuce, nous stylons les points comme les polygones, et le résultat, moins joli à mon goût que les précédents, est tout de même lisible :Exemple de carte de Rennes

Des formats géographiques plus ou moins optimisés

Beaucoup de GeoJSON sont des collections de Features, néanmoins, pour optimiser les topologies, on utilise également parfois des TopoJSON. Leaflet ne les gère pas nativement, cependant, il suffit d'y ajouter le plugin Leaflet-omnivore pour gérer ce format :

var tempLayer = L.geoJson(null, {
  style: {color: '#293133'}
});
var realLayer = omnivore.geojson('data/source.geojson', null, tempLayer);

Une prise en compte de scrutins à 2 tours

Le script de base est conçu pour récupérer un seul fichier de résultats, l'utiliser pour styler le GeoJSON des géographies concernées par le vote, et l'afficher. Pour prendre en compte le deuxième tour, il suffit de récupérer un deuxième fichier de résultats, et, s'il est présent, de réaliser les traitements d'ergonomie sur la carte : ajouter une liste des 2 couches, retirer celle du premier tour de la carte pour que celle du deuxième tour soit affichée par défaut, et c'est tout, Leaflet et sa gestion des couches fait le reste pour nous :

var layers = L.control.layers(null, null, {collapsed: false, position: 'topleft'});
layers.addBaseLayer(tour1Layer, '1er tour');
map.removeLayer(tour1Layer);
layers.addBaseLayer(tour2Layer, '2ème tour');
layers.addTo(self.map);

Les couches sont ajoutées comme baseLayer pour être rendues comme des boutons radios, et non comme des cases à cocher (on ne veut pas avoir les 2 en même temps). Leaflet fait le reste pour nous.

Quelques améliorations d'ergonomie

Ajout d'une couche supplémentaire

Nous travaillons sur des données géographiques, il peut être utile d'aider le visiteur à se retrouver, par exemples les régions sur une carte des départements, les cantons sur une carte des bureaux de vote. Pour ça, elections.js supporte un paramètre additionalLayer qui permet d'ajouter une couche géographique supplémentaire (c'est celle qui représente les limites de Fougères sur la deuxième carte de cette article, ou les limites des régions sur notre carte des départements).

Une interface épurée

Leaflet séduit dans un contexte de webmapping moderne en partie grâce à son interface épurée. Pour poursuivre cet objectif, dans la mesure où nous disposons d'un script générique, nous maintenons cette idée, par exemple en supprimant le contrôle de Zoom si le zoom minimal est égal au zoom maximal : à l'initialisation de la map, un simple

zoomControl: (options.minZoom != options.maxZoom)

fait l'affaire !

Pour profiter pleinenement de la carte, même embarquée dans une page web (de site de presse, par exemple), nous utilisons également le plugin Leaflet.fullscreen, permettant au visiteur d'agrandir la zone de carte, et ce sans aucune action nécessaire du côté du site intégrant la carte.

Un fond personnalisé

Enfin, une de nos caractéristiques est d'utiliser régulièrement des fonds personnalisés (comme sur ces cartes historiques ou sur ce fond très travaillé). Pour améliorer le contraste de nos cartes, nous utilisons cette fois encore un fond personnalisé (embarqué par défaut dans le script elections.js).

Conclusion

Il est tout à fait possible que elections.js ne soit pas directement réutilisable dans votre contexte (notamment toute la partie du code assurant la communication pour des intégrations en iframe), cependant vous y trouverez probablement une grosse base de travail pour des cartes de résultats d'élections. Et nous allons de toute façon encore y travailler, pour plus de réutilisabilité, et plus de possibilités !

N'hésitez pas d'ailleurs à nous proposer des améliorations (et même à proposer des Pull Requests ;-)).

 

Enfin, si vous bloquez dans la réalisation de cartes évoluées ou souhaitez vous aussi utiliser des fonds personnalisés, !

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
À Makina, la JS fatigue n'existe pas... 08/02/2017

...car la passion l'emporte

Infrastructure webmapping minimaliste (partie 2) - TileMill Infrastructure webmapping minimaliste (partie 2) - TileMill 12/12/2013

Dans le cadre de notre architecture webmapping minimaliste, nous présentons quelques astuces pour ...

Les nouveautés de la cartographie en ligne 29/10/2013

Les nouvelles tendances en webmapping et les possibilités offertes par les données géographiques ...

Profil d'élévation avec des tuiles vectorielles Profil d'élévation avec des tuiles vectorielles 02/06/2016

Comment calculer un profil d'élévation côté client en utilisant des tuiles vectorielles

Générer des tuiles vectorielles sur mesure avec Django Générer des tuiles vectorielles sur mesure avec Django 02/06/2016

Dans cet article nous allons voir comment générer dynamiquement des tuiles vectorielles ...