To build viz on the Web, we often use HTML for page content, CSS for aesthetics, JavaScript for interaction, SVG for vector graphics… Web as a platform allows a shared representation of the page called Document Object Model (DOC). Interoperability is however lost due to the encapsulation of the DOM with more specialized forms.

A good web viz tool should reach 3 objectives :

  • **Compatibility **: the tool exists in an ecosystem of related components
  • **Debugging **: accessible tools must be designed to support debugging when the inevitable occurs.
  • **Performance **: Visualizations can be greatly enhanced by interaction and animation. Focusing on transformation rather than representation shifts this responsibility to the developer, improving performance while enabling animation and interaction.

D3.js

D3 is a JavaScript library for creating graphs and interactive visualization tools on the web.

D3 stands for Data Driven Document. D3 answers those 3 objectives. D3’s core contribution is a visualization “kernel” rather than a framework. For high-level capability, D3 includes a collection of helper modules that sit on top of the selection-based kernel; these modules are heavily influenced by prior visualization systems, including Protovis.

In D3, we need to think about 2 primary things :

  • the data
  • the document

Regarding the data, we need to :

  • Load and parse the data,
  • Choose an internal data structure to represent them.

For the document, we need to:

  • Choose a representational structure,
  • Define a mapping from the data to that structure.

As stated above, D3 allows to create interactive visualization tools, so the final step could be to make the data interactive.

Since D3 is a web-based solution, we’ll mainly be working with HTML, CSS, JavaScript, and SVG. I’ll assume that you have at least a basic understanding of the roles of HTML, CSS, and JavaScript.

SVG

There are two primary ways to draw directly to a web page: SVG and the HTML Canvas. In D3, we mostly use SVG. SVG stands for Structured Vector Graphics. SVG can be embedded directly in an HTML page.

<svg width="200" height="200">
    <rect x="10" y="10" width="125" height="125" style="fill: red; stroke:black;">
</svg>
</svg>
In SVG, the most common shapes are : - `` - `` - `` - `` ## Project Architecture There are 2 ways to integrate D3 in a webpage : - by calling the library's remotely (through an URL) - by importing the D3 library and putting it into your `js` folder - Project - css/ - data/ - index.html - js/ - d3 - d3.js - d3.min.js - LICENSE ## D3 Integration To indicate our project to use the d3.js library, we simply need to add this line in the header of `index.html` : ``` ``` ## How to create a graph? Building a graph in D3 can be done in a few steps. First of all, you need to create a new `.js` file that will contain the code of the graph. Then, you need to call that file from the HTML page, in the **body** section : ``` ``` We start by creating an empty canvas in the file `myfile.js` : ``` const w = 600 const h = 600 //Create the SVG let svg = d3.select("body") .append("svg") .attr("width", w) .attr("height",h); ``` We create a global variable, `d3` that we will use to interact with the D3 system. If we run this part and inspect the code of the HTML page, we should see something that has the following structure : ``` ``` And more specifically : ``` ``` We then need to load the data (in this case a TSV file) : ``` d3.tsv("data/myfile.tsv") .get( (error, rows) => { console.log("Loaded " + rows.length + " rows"); } ``` The `.get()` method tells us to start loading the file and should call a function. At that moment, all the values are by default strings. We need to convert the data to match their true type : ``` d3.tsv("data/myfile.tsv") .row( (d, i) => { return { intCol: +d.intCol, longCol: +d["Column Name Long"], stringCol: d.stringCol, }; }) .get( (error, rows) => { console.log("Loaded " + rows.length + " rows"); } ``` Using the row method, we specify a type for the input data. Here's what's happening : - we call each column using `d`, a datum (JavaScript dictionary) whose keys are column labels from our TSV files - we put a `+` in from of columns whose type is numeric - we can also call columns whose name contains spaces - we don't put anything in front of string columns since it's the default type ## Enter, update, exit We now need to define what happens on 3 events : - `enter` whenever a new data entry is created - `update` when a value changes - `exit` when a value is deleted The Enter part might correspond to the web page being shown (this is most often the case). So far, let's not consider the Update or Exit. We will now create a small rectangle for each "x:y" couple in our dataset. ``` let dataset = []; function draw() { svg.selectAll("rect") .data(dataset) .enter() .append("rect") ``` This function tells us to append new "rects" to our canvas and what function to apply to all "rects". We then need to add attributes to this function, including which data it should map on the x-axis and the y-axis. ``` let dataset = []; function draw() { svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x", (d) => d.thisColumn) .attr("y", (d) => d.thisOtherColumn) ``` One of the issues at that point is that the data might need to be scaled between the input width and length (600x600) we specified. ``` let dataset = []; var x = d3.scaleLinear() .domain(d3.extent(rows, (d) => d.thisColumn)) .range([0,w]); var y = d3.scaleLinear() .domain(d3.extent(rows, (d) => d.thisOtherColumn)) .range([h,0]); function draw() { svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x", (d) => d.thisColumn) .attr("y", (d) => d.thisOtherColumn) } ``` To summarize, at that point, we created the Canvas, loaded the data, scaled them, and mapped them in a draw function. All that is left for this example is to call the draw function at the end of `myfile.js`, or right after the get method. ``` draw() ``` I've made a small demo of what D3 can be used for at a quite basic level : ![image](https://maelfabien.github.io/assets/images/map_d3.jpg) The tool can be accessed [here](https://maelfabien.github.io/viz), and the code [here](https://github.com/maelfabien/maelfabien.github.io/blob/master/assets/js/hello-france.js). > **Conclusion** : That's it ! I hope this introduction to D3 was interesting. I have so far used D3 on 2-3 projects, and even though some things are tricky to understand, it's a powerful tool. I highly recommend checking D3's documentation, it's fantastic, well illustrated and well written.