Premiers pas avec d3.js

Installation

Il existe plusieurs façons de télécharger et d’utiliser D3.

Téléchargement direct du script

  1. Téléchargez et extrayez [d3.zip][1]
  2. Copiez le dossier résultant dans lequel vous conserverez les dépendances de votre projet
  3. Référencez d3.js (pour le développement) ou d3.min.js (pour la production) dans votre code HTML : <script type="text/javascript" src="scripts/d3/d3.js"></script>

MNP

  1. Initialisez NPM dans votre projet si vous ne l’avez pas déjà fait : npm init
  2. NPM install D3 : npm install --save d3
  3. Référencez d3.js (pour le développement) ou d3.min.js (pour la production) dans votre code HTML : <script type="text/javascript" src="node_modules/d3/build/d3.js"></script>

CDN

  1. Référencez d3.js (pour le développement) ou d3.min.js (pour la production) dans votre HTML : <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs /d3/4.1.1/d3.js"></script>

GITHUB

  1. Obtenez n’importe quelle version de d3.js (pour le développement) ou d3.min.js (pour la production) sur Github : <script type="text/javascript" src="https://raw.githubusercontent.com/d3/d3/v3.5.16/d3.js"></script>

Pour accéder directement à la dernière version, copiez cet extrait :

<script src="https://d3js.org/d3.v4.min.js"></script>

[1] : https://d3js.org/

Qu’est-ce que D3 ? Documents pilotés par les données.

Nous sommes tellement habitués au nom D3.js qu’il est possible d’oublier que D3 est en fait DDD (Data-Driven Documents). Et c’est ce que fait bien D3, une approche basée sur les données de la manipulation DOM (Document Object Model) : D3 lie les données aux éléments DOM et manipule ces éléments en fonction des données limitées.

Voyons une fonctionnalité très basique de D3 dans cet exemple. Ici, nous n’ajouterons aucun élément SVG. À la place, nous utiliserons un SVG déjà présent sur la page, quelque chose comme ceci :

<svg width="400" height="400">
    <circle cx="50" cy="50" r="10"></circle>
    <circle cx="150" cy="50" r="10"></circle>
    <circle cx="210" cy="320" r="10"></circle>
    <circle cx="210" cy="30" r="10"></circle>
    <circle cx="180" cy="200" r="10"></circle>
</svg>

C’est un SVG assez basique, avec 5 cercles. À l’heure actuelle, ces cercles ne sont “liés” à aucune donnée. Vérifions cette dernière allégation :

Dans notre code, nous écrivons :

var svg = d3.select("svg");
var circles = svg.selectAll("circle");
console.log(circles.nodes());

Ici, d3.select("svg") renvoie un objet d3 contenant la balise <svg width="400" height="400"></svg> et toutes les balises enfants, les <circle>s. Notez que si plusieurs balises svg existent sur la page, seule la première est sélectionnée. Si vous ne le souhaitez pas, vous pouvez également sélectionner par identifiant de balise, comme d3.select("#my-svg"). L’objet d3 a des propriétés et des méthodes intégrées que nous utiliserons beaucoup plus tard.

svg.selectAll("circle") crée un objet à partir de tous les éléments <circle></circle> à partir de la balise <svg>. Il peut rechercher dans plusieurs couches, donc peu importe si les balises sont des enfants directs.

circles.nodes() renvoie les balises de cercle avec toutes leurs propriétés.

Si nous regardons la console et choisissons le premier cercle, nous allons voir quelque chose comme ceci :

[![entrez la description de l’image ici][1]][1]

D’abord, nous avons des attributs, puis childNodes, puis children, et ainsi de suite… mais pas de données.

Lions quelques données

Mais que se passe-t-il si nous lions data à ces éléments DOM ?

Dans notre code, il y a une fonction qui crée un objet avec deux propriétés, ‘x’ et ‘y’, avec des valeurs numériques (cet objet est à l’intérieur d’un tableau, vérifiez le violon ci-dessous). Si nous lions ces données aux cercles…

circles.data(data);

C’est ce que nous allons voir si nous inspectons la console :

[![entrez la description de l’image ici][2]][2]

Nous avons quelque chose de nouveau juste avant attributs ! Quelque chose nommé __data__… et regardez : les valeurs de x et y sont là !

Nous pouvons, par exemple, modifier la position des cercles en fonction de ces données. Jetez un œil [à ce violon][3].

C’est ce que D3 fait le mieux : lier des données à des éléments DOM et manipuler ces éléments DOM en fonction des données délimitées.

[1] : http://i.stack.imgur.com/RHt5m.jpg [2] : http://i.stack.imgur.com/jnHL4.jpg [3] : https://jsfiddle.net/m37b4ekL/2/

Graphique à barres simple

index.html

<!doctype html>
<html>
  <head>
    <title>D3 Sample</title>
  </head>
  <body>
    <!-- This will serve as a container for our chart. This does not have to be a div, and can in fact, just be the body if you want. -->
    <div id="my-chart"></div>

    <!-- Include d3.js from a CDN. -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.js"></script>

    <!-- Include our script that will make our bar chart. -->
    <script type="text/javascript" src="chart.js"></script>
  </body>
</html>

chart.js

// Sample dataset. In a real application, you will probably get this data from another source such as AJAX.
var dataset = [5, 10, 15, 20, 25]

// Sizing variables for our chart. These are saved as variables as they will be used in calculations.
var chartWidth = 300
var chartHeight = 100
var padding = 5

// We want our our bars to take up the full height of the chart, so, we will apply a scaling factor to the height of every bar.
var heightScalingFactor = chartHeight / getMax(dataset)

// Here we are creating the SVG that will be our chart.
var svg = d3
  .select('#my-chart')           // I'm starting off by selecting the container.
    .append('svg')               // Appending an SVG element to that container.
    .attr('width', chartWidth)   // Setting the width of the SVG.
    .attr('height', chartHeight) // And setting the height of the SVG.

// The next step is to create the rectangles that will make up the bars in our bar chart.
svg
  .selectAll('rect')                                          // I'm selecting all of the rectangles in the SVG (note that at this point, there actually aren't any, but we'll be creating them in a couple of steps).
  .data(dataset)                                              // Then I'm mapping the dataset to those rectangles.
  .enter()                                                    // This step is important in that it allows us to dynamically create the rectangle elements that we selected previously.
    .append('rect')                                           // For each element in the dataset, append a new rectangle.
      .attr('x', function (value, index) {                    // Set the X position of the rectangle by taking the index of the current item we are creating, multiplying it by the calculated width of each bar, and adding a padding value so we can see some space between bars.
          return (index * (chartWidth / dataset.length)) + padding
        })
      .attr('y', function (value, index) {                    // Set the rectangle by subtracting the scaled height from the height of the chart (this has to be done becuase SVG coordinates start with 0,0 at their top left corner).
        return chartHeight - (value * heightScalingFactor)
      })
      .attr('width', (chartWidth / dataset.length) - padding) // The width is dynamically calculated to have an even distribution of bars that take up the entire width of the chart.
      .attr('height', function (value, index) {               // The height is simply the value of the item in the dataset multiplied by the height scaling factor.
        return value * heightScalingFactor
      })
      .attr('fill', 'pink')                                   // Sets the color of the bars.

/**
 *  Gets the maximum value in a collection of numbers.
 */
function getMax(collection) {
  var max = 0

  collection.forEach(function (element) {
    max = element > max ? element : max
  })

  return max
}

Exemple de code disponible sur https://github.com/dcsinnovationlabs/D3-Bar-Chart-Example

Démo disponible sur https://dcsinnovationlabs.github.io/D3-Bar-Chart-Example/

Bonjour le monde!

Créez un fichier “.html” contenant cet extrait :

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>

d3.select("body").append("span")
    .text("Hello, world!");

</script>

Voir cet extrait en action sur [ce JSFiddle][1].

[1] : https://jsfiddle.net/r1dd5pho/

Graphique D3 simple : Hello World !

Collez ce code dans un fichier HTML vide et exécutez-le dans votre navigateur.

<!DOCTYPE html>

<body>

<script src="https://d3js.org/d3.v4.js"></script>    <!-- This downloads d3 library -->

<script>
//This code will visualize a data set as a simple scatter chart using d3. I omit axes for simplicity.
var data = [        //This is the data we want to visualize. 
                    //In reality it usually comes from a file or database.
  {x: 10,    y: 10},
  {x: 10,    y: 20},
  {x: 10,    y: 30},
  {x: 10,    y: 40},
  {x: 10,    y: 50},
  {x: 10,    y: 80},
  {x: 10,    y: 90},
  {x: 10,    y: 100},
  {x: 10,    y: 110},
  {x: 20,    y: 30},
  {x: 20,    y: 120},
  {x: 30,    y: 10},
  {x: 30,    y: 20},
  {x: 30,    y: 30},
  {x: 30,    y: 40},
  {x: 30,    y: 50},
  {x: 30,    y: 80},
  {x: 30,    y: 90},
  {x: 30,    y: 100},
  {x: 30,    y: 110},
  {x: 40,    y: 120},
  {x: 50,    y: 10},
  {x: 50,    y: 20},
  {x: 50,    y: 30},
  {x: 50,    y: 40},
  {x: 50,    y: 50},
  {x: 50,    y: 80},
  {x: 50,    y: 90},
  {x: 50,    y: 100},
  {x: 50,    y: 110},
  {x: 60,    y: 10},
  {x: 60,    y: 30},
  {x: 60,    y: 50},
  {x: 70,    y: 10},
  {x: 70,    y: 30},
  {x: 70,    y: 50},
  {x: 70,    y: 90},
  {x: 70,    y: 100},
  {x: 70,    y: 110},
  {x: 80,    y: 80},
  {x: 80,    y: 120},
  {x: 90,    y: 10},
  {x: 90,    y: 20},
  {x: 90,    y: 30},
  {x: 90,    y: 40},
  {x: 90,    y: 50},
  {x: 90,    y: 80},
  {x: 90,    y: 120},
  {x: 100,    y: 50},
  {x: 100,    y: 90},
  {x: 100,    y: 100},
  {x: 100,    y: 110},
  {x: 110,    y: 50},
  {x: 120,    y: 80},
  {x: 120,    y: 90},
  {x: 120,    y: 100},
  {x: 120,    y: 110},
  {x: 120,    y: 120},
  {x: 130,    y: 10},
  {x: 130,    y: 20},
  {x: 130,    y: 30},
  {x: 130,    y: 40},
  {x: 130,    y: 50},
  {x: 130,    y: 80},
  {x: 130,    y: 100},
  {x: 140,    y: 50},
  {x: 140,    y: 80},
  {x: 140,    y: 100},
  {x: 140,    y: 110},  
  {x: 150,    y: 50},
  {x: 150,    y: 90},
  {x: 150,    y: 120},
  {x: 170,    y: 20},
  {x: 170,    y: 30},
  {x: 170,    y: 40},
  {x: 170,    y: 80},
  {x: 170,    y: 90},  
  {x: 170,    y: 100},
  {x: 170,    y: 110},
  {x: 170,    y: 120},
  {x: 180,    y: 10},
  {x: 180,    y: 50},
  {x: 180,    y: 120},
  {x: 190,    y: 10},
  {x: 190,    y: 50},
  {x: 190,    y: 120},
  {x: 200,    y: 20},
  {x: 200,    y: 30},  
  {x: 200,    y: 40},
  {x: 210,    y: 80},
  {x: 210,    y: 90},
  {x: 210,    y: 100},
  {x: 210,    y: 110},  
  {x: 210,    y: 120},
  {x: 220,    y: 80},  
  {x: 220,    y: 120},
  {x: 230,    y: 80},  
  {x: 230,    y: 120},
  {x: 240,    y: 90},
  {x: 240,    y: 100},  
  {x: 240,    y: 110},
  {x: 270,    y: 70},
  {x: 270,    y: 80},
  {x: 270,    y: 90},
  {x: 270,    y: 100},  
  {x: 270,    y: 120}
];

//The following code chains a bunch of methods. Method chaining is what makes d3 very simple and concise.
d3.select("body").append("svg").selectAll()  //'d3' calls the d3 library
                                             //'.select' selects the object (in this case the body of HTML)
                                             //'.append' adds SVG element to the body
                                             //'.selectAll()' selects all SVG elements
    .data(data)                              //'.data' gets the data from the variable 'data'
  .enter().append("circle")                  //'.enter' enters the data into the SVG 
                                             //the data enter as circles with '.append("circle")'
    .attr("r", 3)                            //'.attr' adds/alters atributes of SVG, 
                                             //such as radius ("r"), making it 3 pixels
    .attr("cx", function(d) { return d.x; }) //coordinates "cx" (circles' x coordinates)
    .attr("cy", function(d) { return d.y; }) //coordinates "cy" (circles' y coordinates)
    .style("fill", "darkblue");              //'.style' changes CSS of the SVG
                                             //in this case, fills circles with "darkblue" color

</script>

Voici un JSFiddle du tableau.

Vous pouvez également télécharger le fichier HTML déjà créé à partir de GitHub.

La prochaine étape dans l’apprentissage de d3 peut consister à suivre le didacticiel de Mike Bostock (le créateur de d3) pour créer un histogramme à partir de zéro.