Trafic du Métro parisien

Trafic entrant du métro parisien en 2013

Dernière mise à jour le 23/06/2018
d3js3.x leaflet0.7.3
Voir le plan dans un nouvel onglet

Les données

La principale difficultée a été de récupérer les données et surtout de les transformer pour qu'elles soient faciles à manipuler. Ces données ont toutes été récupérées sur le site data.ratp.fr et en voici la liste :

Les lignes de métro ont été réalisé à la main. A partir de toutes ces données, nous avons rassemblé l'ensemble des informations en deux fichiers CSV. Le premier contient la liste des stations avec son nom, sa ville, son identifiant, sa position géographique, sa couleur, son trafic entrant et ses correspondances. Le second contient la liste des lignes avec pour chacune d'elle, son numéro, sa couleur et la liste ordonnée des identifiants de ses stations.

A l'aide d'un programme informatique, nous avons converti ces deux fichiers en fichiers geoJSON afin qu'ils soient facilement manipulables. C'est un point important car plus les données sont structurées et reconnues par la librairie D3JS plus le code pour les mettre en place est facile et concis. Ces deux fichiers contiennent une FeatureCollection.

Voici un extrait du fichier stations.json. Le premier élément présenté ici correspond à la station dont le trafic entrant est le plus important. Le fichier est trié dans le sens du plus gros trafic vers le plus petit, ainsi les plus gros cercles (chaque station est représentée par un cercle dont le diamètre correspond au trafic entrant) seront en-dessous des plus petits. Le type géométrique du format geoJSON utilisé est Point. Les autres propriétés permettent de renseigner la fenêtre d'information affichée en haut à droite.

{
 "type":"Feature",
 "properties":{
	"ID":"1842",
	"STATION":"GARE DU NORD",
	"CITY":"Paris",
	"QUARTER":"10",
	"TRAFIC":"49977513",
	"LINES":"4-5",
	"COLORS":"#BB4D98-#DE8B53"
 },
 "geometry":{
	"type":"Point",
	"coordinates":[
	   2.35470307836603,
	   48.8799654432891
	]
 }
}

L'autre fichier lines.json contient la liste des lignes ordonnée par numéro. Le type géométrique du format geoJSON est ici LineString qui contient les coordonnées ordonnées de chaque station de la ligne.

{
"type": "Feature",
"properties": {
	"LINE": "3bis",
	"COLOR": "#9A9940"
},
"geometry": {
	"type": "LineString",
	"coordinates": [
			[2.40638582344912, 48.8770699912197],
			[2.40485763553065, 48.871951099492],
			[2.40135199013901, 48.868519874537],
			[2.39846223866212, 48.8648347782704]
	]
}
}

A partir de ces deux fichiers, il faut à peine une quinzaine de ligne pour générer le plan du métro parisien. Mais comme nous souhaitons afficher celui-ci en superposition de la carte de Paris, le code est plus complexe car il faut gérer les zooms et déplacements que l'utilisateur peut réaliser.

Création de la carte et projection

Notre choix s'est porté sur les Tiles Stamen et la librairie Leaflet qui présentent l'avantage d'être en noir et blanc avec des variations très faibles. Le plan du métro ressort alors très bien au-dessus de la carte.

var stamen = new L.StamenTileLayer("toner-lite");

var myLayer = L.tileLayer('http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png', {
	attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors, CC-BY-SA',
	subdomains: 'abcd',
	minZoom: 0,
	maxZoom: 20
});

var map = new L.Map("map", {
	center: new L.LatLng(48.853, 2.333),
	zoom: 13,
	layers: [stamen, myLayer],
});

Nous ajoutons le SVG à l'overlayPane de la map et créons les deux groupes pour nos lignes et nos stations. La classe leaflet-zoom-hide permet de rendre plus élégant le zoom en faisant disparaitre les groupes le temps qu'ils soient projettés à nouveau sur la carte.

var svg = d3.select(map.getPanes().overlayPane).append("svg");
var linesGroup = svg.append("g").attr("class", "leaflet-zoom-hide");
var stationsGroup = svg.append("g").attr("class", "leaflet-zoom-hide");

Contrairement aux tutoriaux de création de cartes visibles dans la section D3JS, nous n'utilisons pas une projection standard mais précisons nous-même la façon dont elle fonctionne. Pour cela nous définissons la fonction de projection projectPoint (située à la fin du code de la page plein écran) qui converti une latitude longitude en un point exprimé en pixel. C'est la librairie Leaflet qui assure cette projection.

var transform = d3.geo.transform({point: projectPoint});
var path = d3.geo.path().projection(transform);

function projectPoint(x, y) {
	var point = map.latLngToLayerPoint(new L.LatLng(y, x));
	this.stream.point(point.x, point.y);
}

Chargement des fichiers geoJSON

Il est possible de charger plusieurs fichiers geoJSON pour qu'ils soient tous mis en mémoire au moment voulu. Pour cela, il faut utiliser la fonction queue de D3JS qui attend le chargement de fichiers passés en paramètre de la fonction defer avant d'exécuter la fonction ready.

queue()
	.defer(d3.json, "stations.json")
	.defer(d3.json, "lines.json")
	.await(ready);

Le traitement des fichiers

Dans cette partie sont présentés quelques éléments important du traitement des données, pour le reste n'hésitez pas à voir le code source ou à poser des questions en bas de cette page.

Style fill & opacity des stations

L'opacité et la couleur de remplissage des cercles de chaque station utilisent la propriété COLORS du fichier stations.json. Cette propriété possède une liste de couleurs séparées par des tirets. S'il n'y a qu'une couleur alors nous remplissons le cercle avec cette couleur et lui associons une opacité de 1, sinon le cercle est gris et légèrement transparent.

.style("fill", function(d) { return (d.properties.COLORS.indexOf('-') > 0 ? "#B8B8B8" : d.properties.COLORS); })
.style("opacity", function(d) { return (d.properties.COLORS.indexOf('-') > 0 ? "0.7" : "1"); })

z-index des stations

Le z-index est fonction du trafic entrant de la station, ainsi les cercles les plus gros se retrouvent en-dessous de plus petits.

.style("z-index", function(d){ return Math.floor(50 - (d.properties.TRAFIC / 1000000)); })

mouseover & mouseout sur les stations

Chaque station du fichier geoJSON contient la liste des lignes et les couleurs correspondantes (les deux propriétés sont ordonnées de la même façon). Lorsque nous construisons les lignes nous leur associons l'id suivant : 'l' + d.properties.LINE. Ainsi lorsque l'utilisateur passe la souris sur une station nous somme capable de sélectionner toutes les lignes de cette station pour les colorées en noir. De la même façon nous pouvons lorsque l'utilisateur sors de la station remettre la couleur d'origine. Le code est assez simple car le fichier geoJSON a été pensé dans ce but.

.on("mouseover", function(d) {
		// Remplissage du DIV d'information
			  
		var lines = d.properties.LINES.split("-");
		for (i = 0; i < lines.length; ++i) {
			d3.selectAll("#l" + lines[i]).style("stroke", "black");
		}
	})
.on("mouseout", function(d) {
	var lines = d.properties.LINES.split("-");
	var colors = d.properties.COLORS.split("-");
	for (i = 0; i < lines.length; ++i) {
		d3.selectAll("#l" + lines[i]).style("stroke", colors[i]);
	}
}
Quelques améliorations resteraient à effectuer :

En réponse au commentaire de Bilouette

Bilouette, qui a posté un commentaire, voudrait pouvoir mettre certaines lignes du métro en pointillé, ce qui peut-être utile pour une ligne dont la construction n'est pas encore achevée. Comme il l'indique il faut effectivement utiliser la propriété stroke-dasharray et c'est très simple à mettre en oeuvre :

featureLine = linesGroup.selectAll("lines")
	.data(lines.features)
	.enter()
	.append("path")
	.attr('class', 'line')
	.attr('stroke-dasharray', function(d) { return (d.properties.LINE === '12' ? "5,5" : "0,0"); })
	.attr('id', function(d) { return 'l' + d.properties.LINE; })
	.attr("d", path)
	.style("stroke", function(d) { return d.properties.COLOR; });

Il suffit donc d'ajouter cet attribut et de faire en sorte qu'il dépende de nos données. Ici nous avons simplement mis des pointillés si le numéro de la ligne est 12 mais on peut modifier le fichier JSON pour ajouter une nouvelle propriété. Notez qu'en utilisant "0,0" comme valeur cela revient à une ligne sans pointillé. Si une partie seulement de la ligne de métro doit être en pointillé le plus simple est surement de créer deux lignes différentes et de trouver un moyen pour que la sélection de la ligne inclue les deux.

Le résultat est visible ici : Lignes pointillées.

A suivre : Tremblements de Terre Voir le tutoriel

comments powered by Disqus