D3 (short for Data-Driven Documents) is a Javascript library to manipulate documents with given data.
In this guide, we will set up the environment with d3js, explore some basic concepts, and a bar chart which you can build directly with d3js, like this:
Then, we will provide some "next-step" tasks, as well as links to more information and references. Let's get started.
There are a few options to set up a d3js environment on your machine, and we will explore each of them in this section.
First of all, you can use d3js in a vanilla <script>
tag, like this:
1<script src="https://d3js.org/d3.v5.min.js"></script>
This will expose a d3
global variable, and you can verify this by typing
1console.log(d3.version);
in the console of your browser.
This statement will print out the version of d3js you are using, which is 5.9.2
at the tie of this writing.
The second option is to install d3js via a package manager, like npm
or yarn
, create a bundle with a bundler, and import d3 accordingly.
1import * as d3 from "d3";
The third option is to use d3js in nodejs, as such:
1var d3 = require("d3");
For the simplicity of this guide, we use the first approach (with a <script>
tag) to set up our environment.
d3-scale
for abstract-data-to-visual-representation MappingWhen directly programming with SVG (short for 'Scalable Vector Graphics'), typically you will do the following for a simple rectangle:
1<svg>
2 <g>
3 <rect x="0" y="0" height="100" width="50">
4 </rect>
5 </g>
6</svg>
As you can imagine, in a bar chart, we need to create many <rect>
elements, calculate their attributes, and attach them to the <svg>
element
This is a daunting task by itself, and d3-scale
can help us to do the calculation.
From the official documentation, we will use the scaleBand()
method for x
, and scaleLinear()
for y
.
These are the building blocks in our case for calculating the x
, y
, height
and width
attributes for the rectangles.
We will use the following logic to create the x
and y
scale functions:
1var x = d3.scaleBand()
2 .domain(DOMAIN_OF_DATA)
3 .range([RANGE_LEFT, RANGE_RIGHT]);
4
5var y = d3.scaleLinear()
6 .domain([0, MAX_OF_VALUE_DATA])
7 .range([RANGE_BOTTOM, RANGE_TOP]);
Note that scales does the mapping from domain
to range
.
d3-axis
Besides the rectangles, we also need to add the x-axis and y-axis in our bar chart.
This is where d3-axis
comes in handy.
We would like to have a bottom axis for x
, and a left axis for y
.
Here are the code snippets to create them:
1var xAxis = g => g
2 .attr("transform", `translate(0,${height - margin.bottom})`)
3 .call(d3.axisBottom(x));
4
5var yAxis = g => g
6 .attr("transform", `translate(${margin.left},0)`)
7 .call(d3.axisLeft(y));
Note that the SVG coordinates start with the top-left point as (0, 0).
This means we need to do a translate
for the y-axis so that the logic (0, 0) is at the bottom left.
More details of SVG transforming can be found here.
data-join
Pattern and Its UsageThe last concept of d3js in use is the 'data-join' pattern, which might look strange at first sight.
1var svg = d3.select('svg');
2var g = svg.append("g");
3
4g.selectAll("rect")
5 .data(data)
6 .join("rect")
7 .attr("x", d => x(d.name))
8 .attr("y", d => y(d.value))
9 .attr("height", d => y(0) - y(d.value))
10 .attr("width", x.bandwidth());
Essentially, the above code snippet creates a few rect
elements with given 'data', and 'join' them accordingly.
Then it calls the x
and y
scale functions to map the name-value pairs in the data to the proper x
and y
coordinates on the screen.
It also calculates the height
and width
attributes for each rectangle.
You can verify the result by looking at the result elements in Chrome Developer Tool, for something like this:
1<rect x="41.95402298850573" y="150.11923076923077" height="219.88076923076923" width="17.586206896551726"></rect>
There are a few tutorials online explaining this pattern in d3js, and my personal favorite is this article by the author of d3js.
With all the above concepts explained and code snippets available, let us put everything together to build our bar chart. Note that we have the following components in the chart:
In our html file, we create a svg element:
1<svg height="450" width="600"></svg>
In the javascript, first we’ll define the data variable:
1var data = [
2 {name: "A", value: "0.08167"},
3 {name: "B", value: "0.01492"},
4 {name: "C", value: "0.02782"},
5 {name: "D", value: "0.04253"},
6 {name: "E", value: "0.12702"},
7 {name: "F", value: "0.02288"},
8 {name: "G", value: "0.02015"},
9 {name: "H", value: "0.06094"},
10 {name: "I", value: "0.06966"},
11 {name: "J", value: "0.00153"},
12 {name: "K", value: "0.00772"},
13 {name: "L", value: "0.04025"},
14 {name: "M", value: "0.02406"},
15 {name: "N", value: "0.06749"},
16 {name: "O", value: "0.07507"},
17 {name: "P", value: "0.01929"},
18 {name: "Q", value: "0.00095"},
19 {name: "R", value: "0.05987"},
20 {name: "S", value: "0.06327"},
21 {name: "T", value: "0.09056"},
22 {name: "U", value: "0.02758"},
23 {name: "V", value: "0.00978"},
24 {name: "W", value: "0.0236"},
25 {name: "X", value: "0.0015"},
26 {name: "Y", value: "0.01974"},
27 {name: "Z", value: "0.00074"}
28];
Then, we define the constant variables of height, width, and margin:
1var height = 400;
2var width = 550;
3var margin = ({top: 20, right: 20, bottom: 20, left: 20});
After that comes the x and y scale functions:
1var x = d3.scaleBand()
2 .domain(data.map(d => d.name))
3 .range([margin.left, width - margin.right])
4 .padding(0.1);
5
6var y = d3.scaleLinear()
7 .domain([0, d3.max(data, d => d.value)])
8 .range([height - margin.bottom, margin.top]);
The xAxis and yAxis functions:
1var xAxis = g => g
2 .attr("transform", `translate(0,${height - margin.bottom})`)
3 .call(d3.axisBottom(x));
4
5var yAxis = g => g
6 .attr("transform", `translate(${margin.left},0)`)
7 .call(d3.axisLeft(y));
And finally, use all the above constants and functions:
1var svg = d3.select('svg');
2
3var g = svg.append("g").attr("fill", "orange");
4
5g.selectAll("rect")
6 .data(data)
7 .join("rect")
8 .attr("x", d => x(d.name))
9 .attr("y", d => y(d.value))
10 .attr("height", d => y(0) - y(d.value))
11 .attr("width", x.bandwidth());
12
13svg.append("g").call(xAxis);
14
15svg.append("g").call(yAxis);
Here we go, we have the final bar chart with all the components mentioned above.
There are many different types of visualizations you can do with d3js, and in this guide we merely scratched the surface of it. Some improvement ideas include:
CSS
.d3-transform
.The code example in this guide is inspired by the examples on bl.ocoks.org and observablehq.com, the official d3js website is https://d3js.org/, and D3 In Depths also provides good tutorials for d3js.
The finished project can be found here.
You can find more courses on d3js on Pluralsight: