You are thinking about including some nice charts and graphics into your current project? Maybe you heard about D3.js, as some people claim it the universal JavaScript visualization framework. Maybe you also heard about a steep learning curve. Let’s see if this is really true!
First of all, what is D3.js?
D3.js is an open source JavaScript framework written by Mike Bostock helping you to manipulate documents based on data.
Okay, let’s first have a look at the syntax
Therefore, lets look at the following hello world example. It will append an <h1> element saying ‘Hello World!’ to the content <div> element.
github:01b12bf75e76f0313946
As you can see the syntax is very similar to frameworks like JQuery and obviously, it saves you a lot of code lines as it offers a nice fluent API.
But let’s see how we can bind data to it:
github:a467683c9d194197c7cf
What happens? The data function gets our names array as parameter and for each name we append an <h1> element with a personalized greeting message. For a second, we ignore the selectAll(‘h1’) and enter() method call, as we will explore them later. Looking into the browser we can see the following:
github:098b73639c169a163d24
Not bad for a start! Inspecting the element in the browser, we see the following generated markup:
github:60aeacb4a14deffbd292
This already shows one enourmous advantage of D3.js: You acctually see the generated code and can spot errors easily.
Now, let’s have a closer look at the data-document connection
As mentioned in the beginning, D3.js helps you to manipulate documents based on data. Therefore, we only take care about handing the right data over to D3.js, so the framework can do the magic for us. To understand how D3.js handles data, we’ll first have a look at how data might change over time. Let’s take the document from our last example. Every name is one data entry.
Easy. Now let’s assume new data comes in:
As new data is coming in, the document needs to be updated. The entries of Robert and Maria need to be removed, Sarah and Marc can stay unchanged and Mike, Sam and Nora need a new entry each. Fortunately, using D3.js we don’t have to care about finding out which nodes need to be added and removed. D3.js will take care about it. It will also reuse old nodes to improve performance. This is one key benefit of D3.js.
So how can we tell D3.js what to do when?
To let D3.js update our data, we initially need a data join, so D3.js knows our data. Therefore, we select all existing nodes and connect them with our data. We can also hand over a function, so D3.js knows how to identify data nodes. As we initally don’t have <h1> nodes, the selectAll function will return an empty set.
github:d7a853ab8a5fee6ad144
After the first iteration, the selectAll will hand over the existing nodes, in our case Sarah, Robert, Marc and Maria. So we can now update these existing nodes. For example, we can change their CSS class to grey:
github:a0c4dbb23368256af75b
Additionally, we can tell D3.js what to do with entering nodes, in our case Mike, Sam and Nora. For example, we can add an <h1> element for each of them and set the CSS class to green for each of them:
github:f036e9f219e43a1ac2c7
As D3.js now updated the old nodes and added the new ones, we can define what will happen to both of them. In our cases this will affect the nodes of Mike, Sarah, Sam, Mark and Nora. For example, we can rotate them:
github:82bc714b842638907b4e
Furthermore, we can specify what D3.js will do to nodes like Robert and Maria, that are not contained in the data set any more. Let’s change their CSS class to red:
github:bcaa391068914c862368
You can find the full example code to illustrate the data-document connection of D3.js as JSFiddle here: https://jsfiddle.net/q5sgh4rs/1/
But how to visualize data with D3.js?
Now that we know about the basics of D3.js, let’s go to the most interesting part of D3.js: drawing graphics. To do so, we use SVG, which stands for scalable vector graphics. Maybe you already know it from other contexts. In a nutshell, it’s a XML-based vector image language supporting animation and interaction. Fortunately, we can just add SVG tags in our HTML and all common browsers will display it directly. This also facilitates debugging, as we can inspect generated elements in the browser. In the following, we see some basic SVG elements and their attributes:
To get a better understanding of how SVG looks like, we’ll have a look at it as a basic example of SVG code, generating a rectangle, a line and a circle.
github:c10ce45f74d0ed5b6f55
To generate the same code using D3.js, we need to add an SVG to our content <div> and then append the tree elements with their attributes like this:
github:2a3961919870b9b60286
Of course, for static SVG code, we wouldn’t do this, but as we already saw, D3.js can fill attributes with our data. So we are now able to create charts! Let’s see how this works:
github:185f496aab8c54f8d666
This will draw our first bar chart for us! Have a look at it: https://jsfiddle.net/tLhomz11/2/
How to turn this basic bar chart into an amazing one?
Now that we started drawing charts, we can make use of all the nice features D3.js offers. First of all, we will adjust the width of each bar to fill the available space by using a linear scale, so we don’t have to scale our values by hand. Therefore, we specify the range we want to get values in and the domain we have. In our case, the data is in between 0 and 200 and we would like to scale it to a range of 0 to 400, like this:
github:16777f35437d0bf8d230
If we now specify x values, we just use this function and get an eqivalent value in the right range. If we don’t know our maximum value for the domain, we can use the d3.max() function to calculate it based on the data set we want to display.
To add an axis to our bar chart, we can use the following function and call it on our SVG. To get it in the right position, we need to transform it below the chart.
github:a66699bd4395e897fa21
Now, we can also add interaction and react to user input. For example, we can give an alert, if someone clicks one our chart:
github:8ca1a79b62d12273a4c2
Adding a text node for each line, we get the following chart rendered in the browser:
If you would like to play around with it, here is the code: https://jsfiddle.net/Loco5ddt/
If you would like to see even more D3.js code, using the same data to display a pie chart and adding an update button, look at the following one: https://jsfiddle.net/4eqzyquL/
Data import
Finally, we can import our data in CSV, TSV or JSON format. To import a JSON file, for example, use the following code. Of course, you can also fetch your JSON via a server call instead of importing a static file.
github:8bd93fc0d914e12e914f
What else does D3,js offer?
Just to name a few, D3.js helps you with layouts, geometry, scales, ranges, data transformation, array and math functions, colors, time formating and scales, geography, as well as drag & drop.
There are a lot of examples online: https://github.com/mbostock/d3/wiki/Gallery
TL;DR
+ based on web standards
+ totally flexible+ easy to debug
+ many, many examples online
+ Libaries build on D3.js (NVD3.js, C3.js or IVML)
– a lot of code compared to other libraries
– for standard charts too heavy
Learning more
As this blog post is based on a presentation held at the MunichJS Meetup, you can find the original slides here: http://slides.com/elisabethengel/d3js#/ The recording is available on youTube: https://www.youtube.com/watch?v=EYmJEsReewo
For further information, have a look at:
- https://github.com/mbostock/d3/wikihttps://github.com/mbostock/d3/wiki/API-Reference
- http://bost.ocks.org/mike/
- Getting Started with D3 by Mike Dewar
- Interactive Data Visualization for the Web by Scott Murray (online for free)
- https://github.com/alignedleft/d3-book
If you have any questions or suggestions, feel free to comment