- Published on
Starting with D3
- Authors
- Name
- Christian Miño
- @Christian_sm91
D3 represents Data-Driven Document which means data-oriented documents. D3.js is a JavaScript library for manipulating documents based on data, written by Mike Bostock.
D3 helps to bring the data to life using HTML, SVG, and CSS. D3 has an emphasis on web standards allowing all the modern search engine capabilities, combining powerful visualization components and a data-driven approach to manipulate the DOM.
D3 allows to combine arbitrary data with the DOM and transform the document. For example, you can use D3 to generate a table in HTML of an array of numbers or use the same information to make an interactive bar chart.
Concepts to understand how it works
Web Standards
Before we start using D3 to create visualizations we need to be familiar with web standards.
HyperText Markup Language (HTML)
Document Object Model (DOM)
Cascading Style Sheets (CSS)
Scalable Vector Graphics (SVG)
JavaScript
I assume that you already know or have an idea about HTML, DOM, CSS, and JavaScript, but I will explain what SVG (Scalable Vector Graphics) is
SVG
SVG is a vector image format, what it means is that the image is described as a composition of geometric shapes instead of being defined as a specific set of pixels. The search engine receives commands to draw shapes in specific coordinates.
As the name implies (Scalable Vector) these images have the ability to scale according to the browser window without losing sharpness or distortion. All search engines support SVG except IE 8 down. D3 renders the graphs using SVG.
An example of the implementation of SVG in an HTML document would be as follows:
<svg width="960" height="500"></svg>
Imagine that the <svg>
tag; it’s like the <canvas>
tag; in which you have to specify the size of the box in which the image will be rendered, by default if the unit of measure is not specified, the size will be in pixels.
Now if you want to draw a rectangle, for example, we can draw it inside the <svg>
tag using the <rect>
tag.
<svg width="960" height="500">
<rect x="0" y="0" width="300" height="200"></rect>
</svg>
Like any HTML element, SVG elements can be stylized from the CSS style sheet.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Rectancle SVG</title>
<style media="screen">
rect {
fill: yellow;
}
</style>
</head>
<body>
<svg width="960" height="500">
<rect x="0" y="0" width="300" height="200"></rect>
</svg>
</body>
</html>
Now that we have understood how the format and the <svg>
tag work, we can see how this library works with a simple example, a bar graph.
1) We add the library.
<body>
<script src="//d3js.org/d3.v5.min.js"></script>
</body>
2) Then we have to put a label at the beginning of the body <svg>
in which our graph will be rendered and we specify how big we want the SVG window, in this case, I want a window of 1000 pixels wide and 600 pixels high. We open a new <script>
tag; to start writing our graphic.
<body>
<svg width="1000" height="600"></svg>
<script src="//d3js.org/d3.v5.min.js"></script>
<script type="text/javascript">
var svg = d3.select('svg'),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 50,
},
width = +svg.attr('width') - margin.left - margin.right,
height = +svg.attr('height') - margin.top - margin.bottom,
g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
</script>
</body>
We have also created a variable: SVG, margin, width, height, and g. The first, SVG, what it does is to select the SVG element that we create in the body tag and where our graphic will be rendered; The variable margin is an object in which we are going to specify a margin with respect to the window of the element SVG; The variable width specifies the width of the graph that would be the width of the window SVG — the left margin — the right margin, the same goes for the variable height (which refers to the height of the graph); to end the variable g that inserts a <g>
tag that groups elements within a <svg>
tag, it is the one that is going to group all the elements of the graph and the 50px translation to the right and 20px to the bottom.
3) Now what we have to do is create the axes, for this we have to make a scale according to the data and according to the size of the graph. The D3 library is included with several methods to scaled the data in the graph, basically what those methods require is that we enter a domain and a range.
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1);
var y = d3.scaleLinear()
.rangeRound([height, 0])
d3.tsv("your data .tsv").then((data) => {
x.domain(data.map(d => d.Run))
y.domain([0, d3.max(data, (d) => {
return Number(d.Speed)
})])
As you can notice we are using two types of scales, the linear scale for the y-axis and the band-scale for the x-axis. You may also notice that we use the d3.tsv() method, it is because we are reading the data from a .tsv file that is delimited by spaces.
4) Now let’s insert the axes.
d3.tsv('your data .tsv').then((data) => {
x.domain(data.map((d) => d.Run))
y.domain([
0,
d3.max(data, (d) => {
return Number(d.Speed)
}),
])
g.append('g')
.attr('transform', 'translate(0' + height + ')')
.call(d3.axisBottom(x))
g.append('g').call(d3.axisLeft(y))
})
In the previous code, we insert two elementsg
one for the x-axis and another for the y. For the x-axis, we call the d3.axisBottom()
method and translate it to the bottom of the window and for the axis and use the d3.axisLeft()
method and the result is as follows:
As you can see the axes are already drawn, now what is missing is to draw the bars with the data we have.
5) With the D3.js library, you can insert and delete elements within the SVG window, with this feature we are going to insert the bars of our graph.
d3.tsv('your data .tsv').then((data) => {
x.domain(data.map((d) => d.Run))
y.domain([
0,
d3.max(data, (d) => {
return Number(d.Speed)
}),
])
g.append('g')
.attr('transform', 'translate(0' + height + ')')
.call(d3.axisBottom(x))
g.append('g').call(d3.axisLeft(y))
g.selectAll('.bar')
.data(data)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', (d) => x(d.Run))
.attr('y', (d) => y(Number(d.Speed)))
.attr('width', x.bandwidth())
.attr('height', (d) => (height = y(Number(d.Speed))))
})
The final result would be like this:
This examples was taken from: Aravind Cheekkallur