Maîtriser la Visualisation de Données Interactives avec D3.js et les Technologies Web
Maîtriser la Visualisation de Données Interactives avec D3.js et les Technologies Web

Construire des Graphiques Communs avec D3.js : Barres, Lignes et Secteurs

Contexte du cours : Maîtriser la Visualisation de Données Interactives avec D3.js et les Technologies Web


Introduction : D3.js et l'Art de la Visualisation

Bienvenue dans cette leçon dédiée à la construction des graphiques les plus fondamentaux et les plus utilisés en visualisation de données avec D3.js (Data-Driven Documents). D3.js est une bibliothèque JavaScript extrêmement puissante et flexible qui vous permet de lier des données au Document Object Model (DOM) et de manipuler ce dernier en fonction de ces données. Contrairement à d'autres bibliothèques de graphiques qui offrent des abstractions de haut niveau (où vous spécifiez simplement le type de graphique et passez les données), D3.js vous donne un contrôle total sur chaque pixel et chaque aspect visuel de votre graphique.

Dans cette leçon, nous allons explorer les principes fondamentaux de D3.js en construisant pas à pas trois types de graphiques essentiels :

  • Le graphique à barres (Bar Chart) : Idéal pour comparer des quantités discrètes.
  • Le graphique linéaire (Line Chart) : Parfait pour montrer des tendances temporelles ou des relations continues.
  • Le graphique à secteurs (Pie Chart) : Utile pour visualiser des proportions d'un tout.

Préparez-vous à plonger dans le monde fascinant de la visualisation de données avec D3.js, où vos données prendront vie de manière interactive et significative.

Prérequis

Avant de commencer, assurez-vous d'avoir une compréhension de base des technologies web suivantes :

  • HTML5 : Pour structurer votre page web.
  • CSS3 : Pour styliser vos graphiques et éléments HTML.
  • JavaScript (ES6+) : Pour la logique de programmation et l'interaction.
  • SVG (Scalable Vector Graphics) : D3.js manipule directement des éléments SVG pour dessiner les graphiques. Une connaissance des balises comme <svg>, <rect>, <circle>, <path>, <text> est un plus.

D3.js en Bref : Les Fondamentaux

D3.js fonctionne en manipulant le DOM (principalement SVG) en fonction de vos données. Voici les concepts clés qui sous-tendent presque toutes les visualisations D3.js :

1. Sélections

Au cœur de D3.js se trouvent les sélections. Elles vous permettent de sélectionner un ou plusieurs éléments du DOM et d'appliquer des opérations (modifier des attributs, du style, ajouter des enfants, etc.).

  • d3.select("sélecteur") : Sélectionne le premier élément correspondant au sélecteur CSS.
  • d3.selectAll("sélecteur") : Sélectionne tous les éléments correspondant au sélecteur CSS.
// Exemple de sélection
d3.select("body").append("svg"); // Ajoute un élément SVG au corps de la page
d3.selectAll("p").style("color", "blue"); // Met la couleur du texte de tous les paragraphes en bleu

2. Liaison de Données (Data Binding)

C'est là que la "Data-Driven" de D3.js prend tout son sens. La méthode data() est la pierre angulaire :

  • selection.data(données) : Lie un tableau de données à une sélection d'éléments. Pour chaque donnée du tableau, D3.js tente de trouver un élément DOM correspondant.
  • .enter() : Retourne les placeholders pour les données qui n'ont pas d'éléments DOM correspondants. C'est ici que vous append() de nouveaux éléments.
  • .exit() : Retourne les éléments DOM qui n'ont pas de données correspondantes. C'est ici que vous remove() les éléments obsolètes.
const chiffres = [10, 20, 30];
d3.select("body").selectAll("p") // Sélectionne tous les paragraphes (qui n'existent pas encore)
  .data(chiffres)                // Lie les chiffres aux futurs paragraphes
  .enter()                      // Pour chaque chiffre sans paragraphe existant...
  .append("p")                  // ...crée un nouveau paragraphe
  .text(d => `Chiffre: ${d}`);  // ...et y met le texte du chiffre

3. Fonctions d'Accès aux Données (Accessors)

Lorsque vous liez des données, les fonctions que vous passez aux méthodes D3 (comme attr, style, text) reçoivent deux arguments :

  • d : La donnée courante de l'itération.
  • i : L'index de la donnée courante dans le tableau.

selection.attr("largeur", d => d * 2) : Ici, d représente la valeur de la donnée pour laquelle l'attribut largeur est défini.

4. Échelles (Scales)

Les échelles sont essentielles pour mapper vos données (souvent numériques) à des propriétés visuelles (comme des positions en pixels, des couleurs, des tailles).

  • d3.scaleLinear() : Pour des données continues (nombre, date). Définit un domaine (l'intervalle de vos données) et une plage (l'intervalle de sortie, par exemple, les pixels sur l'écran).
  • d3.scaleBand() : Pour des données catégorielles (noms de pays, mois). Utile pour positionner des barres ou des groupes d'éléments.
  • d3.scaleOrdinal() : Pour mapper des catégories discrètes à des couleurs ou des formes.
const xScale = d3.scaleLinear()
  .domain([0, 100]) // Les données vont de 0 à 100
  .range([0, 500]); // Les pixels vont de 0 à 500

console.log(xScale(50)); // Affiche 250 (le milieu de la plage pour le milieu du domaine)

5. Axes

Les axes sont des éléments visuels qui représentent les échelles sur le graphique. D3.js fournit des générateurs d'axes.

  • d3.axisBottom(échelle) : Crée un axe horizontal en bas.
  • d3.axisLeft(échelle) : Crée un axe vertical à gauche.

Vous utilisez ensuite selection.call(axe) pour dessiner l'axe sur un élément <g> (groupe SVG).

const yScale = d3.scaleLinear().domain([0, 100]).range([200, 0]); // Notez l'inversion pour les Y
const yAxis = d3.axisLeft(yScale);

svg.append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`)
  .call(yAxis);

Structure Commune d'un Graphique D3.js

La plupart des visualisations D3.js suivent une structure similaire :

  1. Préparation du conteneur HTML : Un simple div est souvent suffisant.
  2. Définition des dimensions du graphique :
    • width, height : Dimensions totales de l'SVG.
    • margin : Marges intérieures pour éviter que les éléments du graphique (comme les axes ou les étiquettes) ne soient coupés.
    • innerWidth, innerHeight : Dimensions réelles de la zone de tracé (width - margin.left - margin.right, etc.).
  3. Chargement des données : Si les données ne sont pas directement intégrées, utilisez d3.csv(), d3.json(), d3.tsv() ou d3.fetch() pour les charger de manière asynchrone.
  4. Création de l'élément SVG : Où le graphique sera dessiné.
  5. Création d'un groupe ( <g> ) pour le contenu du graphique : Souvent translaté par les marges pour simplifier le positionnement des éléments internes.
  6. Définition des échelles : Pour X et Y, et parfois pour la couleur ou la taille.
  7. Création des axes : Basés sur les échelles.
  8. Dessin des éléments visuels : Rectangles, cercles, chemins, texte, etc., en liant les données aux éléments SVG.

Construire un Graphique à Barres (Bar Chart)

Un graphique à barres est l'un des types de graphiques les plus simples et les plus efficaces pour comparer des valeurs catégorielles. Chaque catégorie est représentée par une barre dont la longueur (ou hauteur) est proportionnelle à la valeur qu'elle représente.

Étapes Spécifiques pour un Graphique à Barres :

  1. Données : Généralement un tableau d'objets avec une catégorie et une valeur numérique.
    • Ex: [{ "cat": "A", "val": 30 }, { "cat": "B", "val": 80 }]
  2. Échelle X (xScale) : d3.scaleBand() est parfaite pour les catégories. Elle divise une plage continue en bandes discrètes.
    • Domaine : La liste des catégories uniques.
    • Plage : La largeur de la zone de tracé.
  3. Échelle Y (yScale) : d3.scaleLinear() pour les valeurs numériques.
    • Domaine : De 0 au maximum de vos données.
    • Plage : La hauteur de la zone de tracé (attention : l'axe Y des pixels est inversé, 0 est en haut).
  4. Dessin des Barres : Pour chaque donnée, créez un élément <rect>.
    • x : xScale(d.cat)
    • y : yScale(d.val)
    • width : xScale.bandwidth() (méthode de scaleBand)
    • height : innerHeight - yScale(d.val) (la hauteur est mesurée à partir du bas du graphique)

Exemple de Code : Graphique à Barres Simple

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Graphique à Barres D3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        body { font-family: sans-serif; margin: 20px; }
        .bar { fill: steelblue; }
        .axis path, .axis line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }
        .axis text {
            font-size: 10px;
        }
    </style>
</head>
<body>
    <h1>Graphique à Barres Simple</h1>
    <div id="bar-chart-container"></div>

    <script>
        // 1. Données
        const dataBar = [
            { category: "Pommes", value: 45 },
            { category: "Bananes", value: 60 },
            { category: "Cerises", value: 30 },
            { category: "Dattes", value: 75 },
            { category: "Raisins", value: 50 }
        ];

        // 2. Dimensions du graphique
        const margin = { top: 20, right: 30, bottom: 40, left: 40 };
        const width = 600 - margin.left - margin.right;
        const height = 400 - margin.top - margin.bottom;

        // 3. Création de l'élément SVG
        const svgBar = d3.select("#bar-chart-container")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", `translate(${margin.left},${margin.top})`);

        // 4. Définition des échelles
        const xScaleBar = d3.scaleBand()
            .domain(dataBar.map(d => d.category)) // Domaines : les noms des catégories
            .range([0, width])                     // Plage : la largeur du graphique
            .padding(0.1);                         // Espacement entre les barres

        const yScaleBar = d3.scaleLinear()
            .domain([0, d3.max(dataBar, d => d.value)]) // Domaines : de 0 au max de la valeur
            .range([height, 0]);                        // Plage : de la hauteur à 0 (pour l'inversion Y)

        // 5. Ajout des axes
        svgBar.append("g")
            .attr("class", "x-axis axis")
            .attr("transform", `translate(0,${height})`) // Positionne l'axe X en bas
            .call(d3.axisBottom(xScaleBar));             // Applique l'axe X

        svgBar.append("g")
            .attr("class", "y-axis axis")
            .call(d3.axisLeft(yScaleBar));               // Applique l'axe Y

        // 6. Dessin des barres
        svgBar.selectAll(".bar")
            .data(dataBar)
            .enter()
            .append("rect")
            .attr("class", "bar")
            .attr("x", d => xScaleBar(d.category))     // Position X de la barre
            .attr("y", d => yScaleBar(d.value))       // Position Y de la barre (en haut de la barre)
            .attr("width", xScaleBar.bandwidth())    // Largeur de la barre
            .attr("height", d => height - yScaleBar(d.value)); // Hauteur de la barre
    </script>
</body>
</html>

Explication du code du graphique à barres :

  • Données : Un tableau d'objets, chaque objet ayant une category et une value.
  • Dimensions : Définition des marges et des dimensions intérieures pour le contenu du graphique.
  • SVG et Groupe g : Un élément <svg> est créé, et un élément <g> est ajouté à l'intérieur et translaté pour respecter les marges. Tout le contenu du graphique sera dessiné dans ce <g>.
  • xScaleBar (Échelle de bande) : Son domain est mappé aux noms de catégories uniques (dataBar.map(d => d.category)). Sa range est la largeur disponible (width). padding(0.1) ajoute un petit espace entre les barres.
  • yScaleBar (Échelle linéaire) : Son domain va de 0 à la valeur maximale des données. Sa range va de height à 0. Pourquoi height à 0 et non 0 à height ? Parce qu'en SVG, l'origine (0,0) est en haut à gauche. Si une valeur élevée doit être représentée par une barre haute, son "haut" (son attribut y) doit être plus proche de 0 pixel et son "bas" plus proche de height pixels.
  • Axes : d3.axisBottom(xScaleBar) et d3.axisLeft(yScaleBar) génèrent les fonctions pour dessiner les axes. Ces fonctions sont ensuite appelées sur des éléments <g> séparés (.call(...)) pour les dessiner. Le transform sur l'axe X le positionne en bas du graphique.
  • Barres :
    • selectAll(".bar").data(dataBar).enter().append("rect") : C'est le motif classique de D3 pour lier les données. Il sélectionne tous les éléments avec la classe "bar" (qui n'existent pas encore), les lie aux dataBar, puis pour chaque donnée sans correspondance, ajoute un nouveau <rect>.
    • x : Utilise xScaleBar(d.category) pour positionner le coin supérieur gauche de chaque barre.
    • y : Utilise yScaleBar(d.value) pour positionner le coin supérieur gauche de la barre. C'est le point de départ de la barre, qui sera plus haut pour les valeurs plus grandes.
    • width : xScaleBar.bandwidth() calcule la largeur disponible pour chaque barre, en tenant compte du padding.
    • height : height - yScaleBar(d.value) calcule la hauteur réelle de la barre. Si yScaleBar(d.value) est petit (valeur d.value grande), la hauteur sera grande (tirant la barre vers le bas).

Construire un Graphique Linéaire (Line Chart)

Un graphique linéaire est idéal pour visualiser des tendances sur une période continue ou la relation entre deux variables continues. Il relie des points de données par des segments de ligne.

Étapes Spécifiques pour un Graphique Linéaire :

  1. Données : Généralement une série temporelle ou des paires (x, y).
    • Ex: [{ "date": "2023-01-01", "value": 50 }, { "date": "2023-01-02", "value": 55 }]
  2. Échelle X (xScale) : d3.scaleTime() pour les dates, ou d3.scaleLinear() pour des valeurs numériques continues.
    • Domaine : L'intervalle de temps (min à max date) ou de valeurs X.
    • Plage : La largeur de la zone de tracé.
  3. Échelle Y (yScale) : d3.scaleLinear() pour les valeurs numériques.
    • Domaine : De 0 (ou min) au maximum de vos données Y.
    • Plage : La hauteur de la zone de tracé (attention : l'axe Y des pixels est inversé).
  4. Générateur de Ligne (d3.line()) : C'est une fonction qui prend un tableau de données et retourne la chaîne de caractères d pour l'attribut d d'un élément <path> SVG.
    • line.x(d => xScale(d.date)) : Spécifie comment obtenir la coordonnée X pour chaque point.
    • line.y(d => yScale(d.value)) : Spécifie comment obtenir la coordonnée Y pour chaque point.
  5. Dessin de la Ligne : Un seul élément <path> est créé, et son attribut d est défini par le générateur de ligne appliqué aux données.

Exemple de Code : Graphique Linéaire Simple

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Graphique Linéaire D3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        body { font-family: sans-serif; margin: 20px; }
        .line {
            fill: none;
            stroke: steelblue;
            stroke-width: 2px;
        }
        .axis path, .axis line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }
        .axis text {
            font-size: 10px;
        }
    </style>
</head>
<body>
    <h1>Graphique Linéaire Simple</h1>
    <div id="line-chart-container"></div>

    <script>
        // 1. Données (Exemple de série temporelle)
        const dataLine = [
            { date: "2023-01-01", value: 30 },
            { date: "2023-01-02", value: 32 },
            { date: "2023-01-03", value: 28 },
            { date: "2023-01-04", value: 35 },
            { date: "2023-01-05", value: 38 },
            { date: "2023-01-06", value: 40 },
            { date: "2023-01-07", value: 36 }
        ];

        // Parser les dates
        const parseDate = d3.timeParse("%Y-%m-%d");
        dataLine.forEach(d => {
            d.date = parseDate(d.date);
            d.value = +d.value; // Convertir en nombre
        });

        // 2. Dimensions du graphique
        const margin = { top: 20, right: 30, bottom: 40, left: 40 };
        const width = 600 - margin.left - margin.right;
        const height = 400 - margin.top - margin.bottom;

        // 3. Création de l'élément SVG
        const svgLine = d3.select("#line-chart-container")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", `translate(${margin.left},${margin.top})`);

        // 4. Définition des échelles
        const xScaleLine = d3.scaleTime()
            .domain(d3.extent(dataLine, d => d.date)) // Domaines : étendue des dates
            .range([0, width]);                       // Plage : largeur du graphique

        const yScaleLine = d3.scaleLinear()
            .domain([0, d3.max(dataLine, d => d.value)]) // Domaines : de 0 au max de la valeur
            .range([height, 0]);                       // Plage : de la hauteur à 0 (pour l'inversion Y)

        // 5. Ajout des axes
        svgLine.append("g")
            .attr("class", "x-axis axis")
            .attr("transform", `translate(0,${height})`)
            .call(d3.axisBottom(xScaleLine).tickFormat(d3.timeFormat("%b %d"))); // Format de date pour les ticks

        svgLine.append("g")
            .attr("class", "y-axis axis")
            .call(d3.axisLeft(yScaleLine));

        // 6. Générateur de ligne
        const lineGenerator = d3.line()
            .x(d => xScaleLine(d.date)) // Fonction pour la coordonnée X
            .y(d => yScaleLine(d.value)); // Fonction pour la coordonnée Y

        // 7. Dessin de la ligne
        svgLine.append("path")
            .datum(dataLine) // Utilisation de datum() car c'est une seule ligne pour toutes les données
            .attr("class", "line")
            .attr("d", lineGenerator); // L'attribut 'd' est généré par lineGenerator
    </script>
</body>
</html>

Explication du code du graphique linéaire :

  • Données : Un tableau d'objets avec une date (chaîne) et une value.
  • parseDate : D3.js a des utilitaires pour travailler avec les dates. d3.timeParse("%Y-%m-%d") crée une fonction qui convertit une chaîne de caractères au format "YYYY-MM-DD" en un objet Date JavaScript. Il est crucial de parser vos dates avant de les utiliser avec d3.scaleTime().
  • xScaleLine (Échelle de temps) : Son domain est l'étendue (d3.extent) des dates dans vos données.
  • yScaleLine (Échelle linéaire) : Similaire à celle du graphique à barres, pour les valeurs numériques.
  • Axes : Similaires au graphique à barres. Notez tickFormat(d3.timeFormat("%b %d")) pour formater les étiquettes de l'axe X.
  • lineGenerator : d3.line() crée un générateur de chemin SVG.
    • lineGenerator.x(d => xScaleLine(d.date)) : Indique comment obtenir la coordonnée X pour chaque point de la ligne à partir de la date.
    • lineGenerator.y(d => yScaleLine(d.value)) : Indique comment obtenir la coordonnée Y pour chaque point à partir de la valeur.
  • Dessin de la ligne :
    • svgLine.append("path") : Ajoute un élément <path> SVG.
    • .datum(dataLine) : C'est une différence clé par rapport à data(). datum() lie tout le tableau de données à un seul élément DOM. C'est approprié ici car la ligne est un unique chemin SVG généré à partir de toutes les données.
    • .attr("d", lineGenerator) : L'attribut d d'un <path> définit sa forme. Nous passons le lineGenerator directement ici. D3.js appellera lineGenerator(dataLine) pour obtenir la chaîne de chemin SVG.

Construire un Graphique à Secteurs (Pie Chart)

Un graphique à secteurs est utilisé pour montrer la proportion de chaque catégorie par rapport au total. Il divise un cercle en "tranches" (secteurs), où la taille de chaque tranche est proportionnelle à la valeur qu'elle représente.

Étapes Spécifiques pour un Graphique à Secteurs :

  1. Données : Un tableau d'objets avec une catégorie et une valeur numérique.
    • Ex: [{ "label": "Rouge", "value": 100 }, { "label": "Bleu", "value": 200 }]
  2. Générateur de Secteurs (d3.pie()) : Prend un tableau de données numériques et calcule les angles de début et de fin pour chaque "tranche" du graphique à secteurs.
    • pie.value(d => d.value) : Indique quelle propriété de l'objet de données représente la valeur.
  3. Générateur d'Arc (d3.arc()) : Prend les angles calculés par d3.pie() et retourne la chaîne de caractères d pour l'attribut d d'un élément <path> SVG qui représente l'arc (la tranche).
    • arc.outerRadius(rayon) : Le rayon extérieur du graphique.
    • arc.innerRadius(rayon) : Si 0, c'est un cercle plein. Si > 0, c'est un anneau (donut chart).
  4. Échelle de Couleurs (d3.scaleOrdinal()) : Pour attribuer une couleur unique à chaque catégorie.
    • Domaine : La liste des catégories uniques.
    • Plage : Un tableau de couleurs. D3.js fournit des schémas de couleurs prêts à l'emploi (ex: d3.schemeCategory10).
  5. Dessin des Tranches : Pour chaque "arc" généré par d3.pie(), créez un élément <path>. L'attribut d de ce <path> sera généré par d3.arc().
  6. Ajout des Étiquettes : Des éléments <text> pour afficher les noms de catégories ou les pourcentages. Les étiquettes sont souvent positionnées au centre de chaque arc.

Exemple de Code : Graphique à Secteurs Simple

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Graphique à Secteurs D3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        body { font-family: sans-serif; margin: 20px; }
        .arc path {
            stroke: #fff;
        }
        .arc text {
            font-size: 11px;
            text-anchor: middle;
            fill: white;
        }
    </style>
</head>
<body>
    <h1>Graphique à Secteurs Simple</h1>
    <div id="pie-chart-container"></div>

    <script>
        // 1. Données
        const dataPie = [
            { label: "France", value: 120 },
            { label: "Allemagne", value: 90 },
            { label: "Italie", value: 70 },
            { label: "Espagne", value: 60 },
            { label: "Royaume-Uni", value: 80 }
        ];

        // 2. Dimensions du graphique
        const widthPie = 400;
        const heightPie = 400;
        const radius = Math.min(widthPie, heightPie) / 2;

        // 3. Création de l'élément SVG
        const svgPie = d3.select("#pie-chart-container")
            .append("svg")
            .attr("width", widthPie)
            .attr("height", heightPie)
            .append("g")
            .attr("transform", `translate(${widthPie / 2},${heightPie / 2})`); // Centre le groupe au milieu de l'SVG

        // 4. Générateur de couleurs
        const colorScale = d3.scaleOrdinal()
            .domain(dataPie.map(d => d.label)) // Domaine : les labels des catégories
            .range(d3.schemeCategory10);       // Plage : un schéma de couleurs prédéfini par D3

        // 5. Générateur de secteurs (Pie Generator)
        const pieGenerator = d3.pie()
            .value(d => d.value)     // Indique quelle propriété de la donnée est la valeur
            .sort(null);             // Ne pas trier les arcs par défaut (laisse l'ordre des données)

        // 6. Générateur d'arcs (Arc Generator)
        const arcGenerator = d3.arc()
            .innerRadius(0)         // Pour un graphique à secteurs plein (pas de trou au milieu)
            .outerRadius(radius);   // Le rayon extérieur du secteur

        const outerArcGenerator = d3.arc() // Un arc légèrement plus grand pour positionner les étiquettes
            .innerRadius(radius * 0.9)
            .outerRadius(radius * 0.9);

        // 7. Calcul des arcs à partir des données
        const arcs = pieGenerator(dataPie);

        // 8. Dessin des tranches (paths)
        const g = svgPie.selectAll(".arc")
            .data(arcs)
            .enter()
            .append("g")
            .attr("class", "arc");

        g.append("path")
            .attr("d", arcGenerator) // Utilise le générateur d'arc pour dessiner la tranche
            .attr("fill", d => colorScale(d.data.label)); // Utilise l'échelle de couleurs

        // 9. Ajout des étiquettes de texte
        g.append("text")
            .attr("transform", d => `translate(${outerArcGenerator.centroid(d)})`) // Positionne le texte au centre de l'arc
            .attr("dy", "0.35em") // Ajustement vertical
            .text(d => `${d.data.label} (${(d.data.value / d3.sum(dataPie, dt => dt.value) * 100).toFixed(1)}%)`); // Affiche label et pourcentage
    </script>
</body>
</html>

Explication du code du graphique à secteurs :

  • Données : Tableau d'objets avec un label et une value.
  • Dimensions : widthPie, heightPie, et radius (qui est la moitié du plus petit côté pour que le cercle tienne).
  • SVG et Groupe g : L'élément <g> est translaté au centre de l'SVG. Cela simplifie les calculs de positionnement, car tous les arcs seront dessinés par rapport à cette nouvelle origine (0,0) qui est le centre du cercle.
  • colorScale (Échelle ordinale) : Mappe les labels des catégories à une palette de couleurs (d3.schemeCategory10 est un tableau de 10 couleurs prédéfinies).
  • pieGenerator (d3.pie()) : C'est la fonction magique pour les secteurs. Elle prend un tableau de données brutes et calcule pour chaque donnée les angles de début et de fin nécessaires pour former la tranche.
    • .value(d => d.value) : Lui indique quelle propriété de vos données doit être utilisée pour calculer la taille des tranches.
    • .sort(null) : Par défaut, d3.pie() trie les tranches par valeur. null désactive ce tri, conservant l'ordre des données d'origine.
  • arcGenerator (d3.arc()) : Ce générateur prend les objets d'arc produits par pieGenerator et les convertit en chaînes de chemins SVG (d attribute).
    • .innerRadius(0) : Crée un cercle plein. Mettez une valeur > 0 pour un donut chart.
    • .outerRadius(radius) : Définit le rayon extérieur du cercle.
  • outerArcGenerator : Un deuxième générateur d'arc avec un rayon légèrement plus grand. Il est utilisé uniquement pour calculer la position des étiquettes, les plaçant juste à l'extérieur des tranches.
  • arcs = pieGenerator(dataPie) : Exécute le générateur de secteurs sur vos données pour obtenir le tableau d'objets d'arc (chacun avec startAngle, endAngle, data, etc.).
  • Dessin des Tranches :
    • svgPie.selectAll(".arc").data(arcs).enter().append("g") : Crée un groupe <g> pour chaque arc. C'est pratique car chaque groupe peut contenir à la fois le path de la tranche et son text d'étiquette, et ils peuvent être transformés ensemble.
    • g.append("path").attr("d", arcGenerator) : Pour chaque groupe g, ajoute un <path> dont l'attribut d est généré par arcGenerator (qui prend l'objet d'arc comme input).
    • attr("fill", d => colorScale(d.data.label)) : Remplit la tranche avec la couleur correspondant à son label. Notez d.data.label car d est l'objet d'arc (qui contient l'objet de données original sous d.data).
  • Ajout des Étiquettes :
    • g.append("text") : Ajoute un élément <text> à chaque groupe d'arc.
    • attr("transform", d => \translate(${outerArcGenerator.centroid(d)})`): La méthodecentroid()` de l'arc generator calcule le point central d'un arc, parfait pour positionner le texte.
    • attr("dy", "0.35em") : Un petit ajustement vertical pour le texte.
    • text(...) : Affiche le label et un pourcentage calculé.

Conclusion et Prochaines Étapes

Félicitations ! Vous avez maintenant une solide compréhension des concepts fondamentaux de D3.js et avez appris à construire trois des graphiques les plus couramment utilisés : les graphiques à barres, linéaires et à secteurs.

Points Clés à Retenir :

  • D3.js est une bibliothèque puissante pour manipuler le DOM en fonction de vos données.
  • Les sélections (d3.select, d3.selectAll) sont le point de départ pour interagir avec le DOM.
  • La liaison de données (.data().enter().append()) est la mécanique centrale pour créer des éléments visuels à partir de vos données.
  • Les échelles (d3.scaleLinear, d3.scaleBand, d3.scaleTime, d3.scaleOrdinal) sont cruciales pour mapper les données aux propriétés visuelles (position, taille, couleur).
  • Les générateurs (d3.axis, d3.line, d3.pie, d3.arc) simplifient la création de formes SVG complexes et d'éléments d'interface utilisateur.
  • La convention des marges est une bonne pratique pour organiser vos graphiques.

Prochaines Étapes :

D3.js est vaste, et ces bases ne sont que le début. Voici quelques pistes pour approfondir vos connaissances :

  • Interactions et Transitions : Ajoutez des fonctionnalités interactives (tooltips au survol, filtres, zoom/pan) et des animations fluides (.transition()) pour rendre vos graphiques dynamiques et engageants.
  • Chargement de Données Externes : Apprenez à charger des données depuis des fichiers CSV, JSON ou des API en utilisant d3.csv(), d3.json() ou d3.fetch().
  • Réactivité : Adaptez vos graphiques pour qu'ils se redimensionnent automatiquement avec la fenêtre du navigateur.
  • Composants Réutilisables : Organisez votre code en fonctions ou classes JavaScript pour créer des composants de graphique réutilisables.
  • Autres Types de Graphiques : Explorez d'autres visualisations avec D3.js, comme les scatter plots, les heatmaps, les arbres, les graphes de réseau, ou les cartes géographiques.
  • D3.js v4+ et ES6 : Familiarisez-vous avec les dernières versions de D3.js et les fonctionnalités modernes de JavaScript.

La visualisation de données est un mélange d'art et de science. Avec D3.js, vous avez les outils pour raconter des histoires puissantes et informatives à travers vos données. Continuez à expérimenter, à apprendre et à créer !