Overview
Data visualization is a important part of any software application. It not only helps in understanding easily and quickly, but sometimes also present hidden information in a simple way which would take ages for laymen user to understand. In this article, we will try to understand one such data visualization technology, D3.js, which has gained lot of popularity among data visualization engineers recently.
This article is meant for beginners in D3.js, however, as D3.js is a web based technology, readers should be well aware of common web technologies like, HTML, CSS, AJAX etc to take advantage of this article. Also, since D3.js itself is a JQuery based technology, having good knowledge in JQuery is also required, however basic knowledge of SVG will be enough.
This article covers very basic concepts of D3.js. Aim is to get beginners started with technology, so I don't want to confuse beginners with lot of extra information at this moment. I have planned some more article in future which will cover advance concept as well.
As a server side technology, I have used ASP.Net MVC 4.0, However, it will make no difference if you want to use any other server side technology as D3.js is a client side technology and server side technology only serves purpose of sending data to client side which will be processed by D3.Js.
Introduction
D3.js (or just D3 for Data-Driven Documents) is a JavaScript library for producing dynamic, interactive data visualizations in web browsers.
It is basically API library which uses SVG, JSON, JQuery, HTML5 and CSS for achieving effective data visualization.
Technically, D3.js is neither a charting library nor a visualization library or a graphic library. It is a very thin layer on top of modern web technologies to help visualization engineers build powerful data visualization. Embedded within an HTML webpage, the JavaScript D3.js library uses pre-built JavaScript functions to select elements, create SVG objects, style them, or add transitions or dynamic effects to them, which can easily be decorated with CSS if needed.
Large datasets can be easily bound to SVG objects using simple D3.js functions to generate rich text/graphic charts and diagrams. The data can be in various formats, most commonly JSON and CSV .
Why to Use D3.js
There are numerous library available in market today, both free and paid, then why should one go for using D3.js. Here are few reasons -
- In contrast to many other libraries, D3.js allows great control over the final visual result.
- Free Open Source technology with all source code available on github.
- Simple with ease of use and freedom.
- Interactive
- Powerful, you can draw almost any chart with D3.js
- Lot of tools already available with working mocks.
Basic Terminology
Chart
Chart is the placeholder in which your graph will be drawn. Generally it will be a simple empty HTML Div tag which will contain our D3Js chart.
Scale are the functions which map pixels in your chart to some unit of your graph. Your chart need to have a coordinate system and through scale you define coordinate system of your graph.
Here, the x-axis goes from 2013 to 2015, and the y-axis goes from $0 to $5000. However, the SVG is drawn in a box that’s about 200 by 300 pixels. Dates and pixels don’t map to one another on their own, so we have to specify a mapping somehow.
Note that the y-axis flips! The SVG origin, (0, 0) is in the top left, but in this graph, the origin is the bottom left.
For defining any scale you need domain. A domain is any set of values inside which values of your data lies. For example, revenues of 5 years may be [$2500.00,$3100.00,$1005.00,$5000.00,$3400.00], for this data domain may be [$0.00, $5000,00].
There are three types of scales - Quantitative Scales, Ordinal Scales, Time Scales.
Quantitative Scales - Quantitative scale have continuous domain, for example set of real number, dates etc. There are numerous subtypes of quantitative scale like log scale, power scale etc. but most commonly used quantitative scale is linear scale. In this scale, the mapping is linear in that the output range value y can be expressed as a linear function of the input domain value x. For example if a value v1 = 2500 takes takes 200 pixels in y axis, v2 = 5000 should typically take 400 pixels in y axis.
Ordinal Scales - Ordinal scales are used for discrete input domains, such as names, countries, groups etc.
Time Scales - Time scales are used for time values.
Below image shows use of both quantitative and ordinal scales. Left chart is showing sales by region in which x-axis is representing regions and y-axis is showing domain values for sales. Right chart is showing sales by year where x-axis is representing year data while y-axis is showing domain values for sales.
Axes
Once you have defined scales, you need reference lines to represent your data. These reference lines are your axes. D3.js library provides many methods and properties through which you can draw and decorate your axes in numerous ways.
Some commonly used functions you may need to define your axes -
d3.svg.axis() - Defines axis with default properties.
axis.scale([scale]) - If [scale] is defined, sets the scale and returns the axis. If scale is not specified, returns the current scale which defaults to a linear scale.
axis.orient([orientation]) - If [orientation] is specified, sets the orientation and returns the axis. If orientation is not specified, returns the current orientation which defaults to "bottom".
Orientation decides direction of a axis and positions of tick labels in the axis. There can be 4 valid values -
"top" - horizontal axis with ticks above the domain path
"bottom" - horizontal axis with ticks below the domain path
"left" - vertical axis with ticks to the left of the domain path
"right" - vertical axis with ticks to the right of the domain path
axis.ticks([arguments…]) - This method decides count and values of ticks to be shown in axis. Default value is 10.
Arguments will depend on type of scale. For example , For showing sales data, count of the ticks can passed simply which will distribute your domain values evenly over the scale in number of counts passed as argument, while for showing time values in a scale you might need to pass both time interval and tick count such as axis.ticks(d3.time.year, 1)
axis.tickValues([values]) - This method takes an array as an argument. If array [values] is specified, tick labels will be taken from this array in place of default array.
A Simple Example
Lets take a simple graph as an example to understand use of D3 API's. Lets say you have following data in the table for which you need to show a graph in your website -
| |
Year | Sales | 2013 | $2000 | 2014 | $3000 | 2015 | $5000 |
|
References
For D3.js, you need to to have reference of JQuery(download from here) and D3Js(download from here). Alternatively, you can take reference from CDN directly also.
Data
For plotting a graph, you need to have some data. In my example, I have defined provided data in function itself to keep things simple but in a typical real life application data will come from server.
JavaScript -
var yearData;
var salesData;
var data =
[
{ 'Year': '2012', 'Sale': 2000 },
{ 'Year': '2014', 'Sale': 3000 },
{ 'Year': '2015', 'Sale': 5000 }
]
yearData = GetYears(data)
salesData = GetSales(data)
GetYear(data) and GetSales(data) function can be defined like -
JavaScript -
function GetYears(data) {
var result = [];
for (var i in data)
result.push(data[i].Year);
return result;
}
function GetSales(data) {
var result = [];
var max = 0.0;
result.push(max);
for (var i in data) {
if (max < data[i].Sale) {
max = data[i].Sale
}
}
result.push(max+50);
return result;
}
Here, 'data' is a Json object, which we can get from server from a simple AJAX call. I have have created two simple arrays, 'yearData' and 'salesData' from this object which will help us define our axes.
Chart
As explained earlier, chart is a canvas for our graph. We need to have a simple empty div tag, which we can convert to our chart object.
HTML -
<div id="chart"></div>
JavaScript -
var margin = { top: 20, right: 30, bottom: 30, left: 40 },
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var chart = d3.select("#chart")
.append("svg")
.attr("width", width + (2 * margin.left) + margin.right)
.attr("height", height + margin.top + margin.bottom);
Scales and Axes
Now you need to map your chart with the data units. For this we define scales. Any scale have a domain and a range. While domain represent your data values, range represents your chart area(pixels). Here, I have used ordinal scale for representing year data.
JavaScript -
var x = d3.scale.ordinal().domain(yearData).rangePoints([margin.left, width]);
var y = d3.scale.linear().domain(salesData).range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom").ticks(data.Year);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left").ticks(10);
Transforming Data
Now we have chart, axes and scale defined, we can transform our data to visual display.
JavaScript -
var valueline = d3.svg.line()
.x(function (d) { return x(d.Year); })
.y(function (d) { return y(d.Sale); });
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + ",0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sales Data");
chart.append("path")
.attr("class", "line")
.attr("d", valueline(data));
CSS
Lets decorate our chart with some CSS
<style type="text/css">
#chart text{
fill: black;
font: 10px sans-serif;
text-anchor: end;
}
.axis text{
font: 10px sans-serif;
}
.axis path, .axis line{
fill: none;
stroke : #fff;
shape-rendering: crispEdges;
}
body{
background: #1a1a1a;
color : #eaeaea;
padding : 10px;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
</style>
So, You are ready to run code and view results -
Points of Interest
D3.js is a powerful data visualization technology which quickly gaining interest of many data visualization engineers. You can almost draw any kind of charts with it.
This article is not a deep dive but covers very basic concepts of D3.js. Aim is to get beginners started with technology. Please watch the space for more advance topics in D3.js I have planned for future which will cover some more advance concepts.