D3.js
Cette page est en grande partie issue de : Visualisation de données - d3.js
d3.js est une librairie javascript très complète avec beaucoup d’exemples à disposition, avec une personnalisation totale possible. Elle permet l’accès à des primitives SVG permettant toute innovation. Malheureusement, elle est peu accessible directement et assez technique.
Fonctionnement typique
L’idée principale est de lier les données au DOM (Document Object Model), et d’appliquer des transformations, basées sur les données, au document.
Il y a plusieurs concepts spécifiques à bien comprendre pour l’utiliser pleinement :
- Sélection, modification, ajout et insertion d’éléments
- Ajout de données au DOM
- Propriété dynamique, et Transformation
- Chaînage des fonctions
Base
Sélection
Il existe deux fonctions de sélection respectivement d’un seul élément (avec select()) et de l’ensemble des éléments (avec selectAll()) correspondant à la définition passée en paramètre :
var selection1 = d3.select("selecteur");
var selection2 = d3.selectAll("selecteur");
Quand on utilise une sélection d’un seul élément (avec select() donc), mais qu’il existe plusieurs éléments de ce type dans le document, c’est le premier qui est renvoyé.
La sélection se fait de manière identique que pour le CSS :
- "balise" : pour tout ce qui est balise html (div, h1, body, …)
- ".maclasse" : pour le ou les objets de la classe indiquée (indiquée via "class='maclasse'")
- "#identifiant" : pour l’objet (unique normalement) avec cet identifiant (indiquée via "id='identifiant'")
Ces sélecteurs permettent ensuite d’accéder à plusieurs fonctions utiles pour manipuler les objets, comme nous le verrons. Voici trois premières fonctions :
- size() : taille de la sélection
- empty() : sélection vide ou non
- html() : contenu html de la sélection
Modification, ajout et insertion d’éléments
Plusieurs fonctions permettent de modifier les éléments sélectionnés (comme par exemple style() pour appliquer des règles CSS ou html() pour modifier le contenu de la balise). Le code suivant permet de mettre le texte en rouge pour tout le corps de la page
var corps = d3.select("body");
corps.style("color", "red");
Deux fonctions sont utiles pour respectivement insérer un élément HTML fils à la fin (append()) ou au début (insert()) d’un élément père, qui s’utilisent comme suit :
selection.append("balise");
selection.insert("balise");
Exemple
Ici, on sélectionne la balise <body> (qui est vide au départ). Dans cette sélection, on ajoute deux balises div, pour mettre dans la première la taille de la sélection (1 normalement) et dans la seconde le test si elle est vide ou non (normalement false). Enfin, on met le texte de la sélection en rouge (donc tout).
// Sélection de la balise body
var corps = d3.select("body");
// Ajout de deux balises div au corps
var div1 = corps.append("div");
var div2 = corps.append("div");
// Définition du contenu des deux balises
div1.html("Je met du texte ici.");
div2.html("Nombre de div : " + d3.selectAll("div").size());
// Modification de la couleur de la police
corps.style("color", "red");
div2.style("color", "steelblue");
Ajout de données au DOM
Avec la fonction data() sur une sélection, il est possible de lier les données passées en paramètres (ce doit être un tableau) au DOM à la sélection en question. Le code suivant affecte chaque élément du tableau à chaque élément renvoyé par le sélecteur précédent
var selection = d3.selectAll("selecteur");
selection.data(tableau);
S’il y a différence entre la taille de la sélection et la taille du tableau passé en paramètre de data(), il existe deux fonctions utiles pour gérer ces cas :
- enter() : pour gérer les éléments du tableau en plus
- exit() : pour gérer les éléments de la sélection en plus
Propriété dynamique
Sur chaque sélection, on peut appliquer des modifications de style ou de contenu (voire autre), en fonction des données sont liées au DOM. On passe par l’utilisation d’une fonction anonyme, dont les paramètres peuvent être, dans cet ordre :
- la valeur de l’élément du tableau affectée à l’élément
- la position de la valeur dans le tableau
- il est possible de n’utiliser que la valeur, voire aucun paramètre si besoin
var selection = d3.selectAll("selecteur");
selection.data(tableau);
selection.html(function(d, i) {
return "position = " + i + ", valeur = " + d;
})
Exemples
Ajout de données + propriété dynamique
Dans cet exemple, on affecte les données du tableau (qui contient des couleurs) à chaque div du body. Et on affecte un style CSS (la couleur), en prenant comme valeur celle contenu dans le tableau.
HTML
JS
var div = d3.selectAll("div");
div.data(["green", "red", "blue"])
div.style("color", function (d) { return d; });
fonction enter()
Le tableau passé en paramètre de data() est ici plus long que la sélection. Pour les valeurs supplémentaires du tableau (sélectionnées avec le enter()), on ajoute des div (avec append()).
HTML
JS
// div : liste des div présents dans le HTML
var div = d3.select("body").selectAll("div");
/* Le select("body") n'est la que pour s'assurer que les div soient bien
ajoutée dans le body et non après */
// div_data : div avec les données associées
var div_data = div.data(["green", "red", "blue", "orange", "purple"]);
// affectation de la couleur à chaque div
div.style("color", function (d) { return d; });
// div_enter : données en trop
var div_enter = div_data.enter();
// div_nv : nouvelles div ajoutée à partir des données en trop
var div_nv = div_enter.append("div");
// définition du contenu des nouvelles div
div_nv.html("div ajoutée");
// affectation de la couleur à chaque nouvelle div
div_nv.style("color", function (d) { return d; });
fonction exit()
C’est ici le contraire, le tableau est plus petit que la sélection. Pour les éléments de la sélection en trop (sélectionnés avec le exit()), on les supprime (avec remove()).
HTML
JS
// div : liste des div présents dans le HTML
var div = d3.select("body").selectAll("div");
// div_data : div avec les données associées
var div_data = div.data(["green", "red"]);
// affectation de la couleur à chaque div
div.style("color", function (d) { return d; });
// div_exit : div en trop
var div_exit = div_data.exit();
// suppression de ces div en trop
div_exit.remove();
// on peut remplacer par cette ci-dessous, qui change le contenu de la div en trop
// div_exit.html("en trop");