Practical data visualization concepts in D3.js
September 1st, 2016 | By João Samouco | 7 min read
We can use D3.js to manipulate documents based on our data and visualize that same data using SVG, HTML, and CSS.
At the core of D3, we have a framework that allows us to associate any object or array of data with elements on a page, binding them together for further manipulation.
Update data and we visually update the object tied to that data within our document, in real time. We can use any number of visualizations to interpret data and display it as a graph, a chart, an eye-catching animated SVG, or as patterns and gradients.
Once the data and the object are linked, the possibilities of visualizing them are endless. We’ll cover D3.js version 3, but it has since been updated to 4.0.
If you’ve ever used Microsoft Excel to visualize data into charts and graphs, you’ve probably also encountered some frustration with popular spreadsheet software.
The strategic use of accessible data visualization provides a significant competitive advantage. There are entire startups dedicated to building Web Applications that create compelling visual representations based on metrics and various KPIs.
Big data isn’t only valuable to accountants and C-level executives.
Metrics can provide insight into a company’s performance but they shine when you add a layer of interactivity as you visualize your data. Thanks to Mike Bostock, developers now have an Open Source option for crafting Excel-like data visualizations.
Basics
The D3 API needs us to designate a container that will house our visualization. Every element created within D3 must be created within a container otherwise it doesn’t exist. This is typically an SVG but D3 supports HTML and Canvas as well. D3.js can be boiled down to the following formula when binding data to an SVG visualization:
var dataset = [
6, 10, 23, 46, 26, 64, 36, 59, 12, 31, 15, 40,
64, 70, 67, 71, 64, 75, 33, 45];
var svg = d3.select(‘div.myElement’)
.append('svg')
.attr(‘width’, ‘300 px’)
.attr(‘height’, ‘300 px’);
The SVG variable is declared as a D3 selection and will be used for our transformations.
We then append an SVG element to the DOM and include configurations to the output of our data with .attr. In this example, our data is declared as an array but it could also be XML, JSON, or just a plain CSV file. There are several other data formats we can use in D3.
You can load a plain old text file, a TSV, HTML, and even an XMLHttpRequest. To add any elements at all we first have to create our SVG by declaring the area for our visual elements:
var svg = d3.select(‘div.myElement’)
.append('svg')
.attr(‘width’, ‘300 px’)
.attr(‘height’, ‘300 px’);
Think of .select as the equivalent of $() in jQuery, which selects our div in this case. We declare our height and width as attributes for the SVG.
D3 gives us access to shapes like rectangles, circles, ellipses, lines, polygons, and paths.
Adding Data
After we establish our canvas, we add our data. The utility functions available in D3 give us a wide coverage for creating powerful visuals.
For example, data() will load the data required for our document. We have the option of coding in our data but practical applications of D3 will most likely have us parsing data from a CSV or JSON file. A trivial use case would be declaring our data in the following examples:
As JSON
var dataset = {
"first-name": “Hermes ",
"last-name": “Trismegistus ",
};
Or as an array…
var dataset = [5, 10, 15, 20, 25];
var otherset = [{
x: 100,
y: 100
}, {
x: 200,
y: 200
}, {
x: 300,
y: 300
}]
If we wanted to load data from a CSV we’d do something like this:
d3.csv("/data/data.csv", function(data) {
console.log(data);
});
Once data is bound to the SVG we can use any number of included functions to create the graphical elements.
As a rule of thumb for data, we should ensure that we can construct an array from the data we use. In the next few steps, we’ll cover several examples highlighting transformations in D3.
Bar chart aka Histogram
When you’d like to present data in the most efficient way possible, a histogram (better known as a bar chart) will work perfectly. Here’s a simple instance of a bar chart possible in D3:
In our fiddle example, we prefix our rect element to build a bar graph using a rectangle: d3.append(“rect"). The rectangle appended to our SVG is used to represent data in our bar chart in the above fiddle as well as in most cases.
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / dataset.length);
});
D3 subscribes to a declarative programming style. We make our selection and then configure any modifications as attributes within the DOM. This includes any changes to CSS styles, HTML, SVG attributes, texts, and animations.
D3 iterates through our selection, appends, and applies modifications for us. The DOM is abstracted away while still granting us full control of the visualization processes.
Within our code example above we make use of selectAll() to create an empty set filled with our graphical elements:
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
});
data() declares the object or array we will use to be represented in our chart. Then enter() combines our data with the empty set from selectAll() and creates a set of elements that can then be accessed by D3.
append() which binds our selection and establishes the type of visualization by allowing us to choose from the available SVG elements. In this case, we want a ‘rect’ element to build a bar graph.
Next, we define our bar with:
svg.selectAll('rect.bar').data(data)
An example of us positioning a bar chart based on our data would look something like this:
svg.append("rect") // append a rectangle
.attr("x", 100) // position the left of the rectangle
.attr("y", 50) // position the top of the rectangle
.attr("height", 100) // set the height
.attr("width", 200) // set the width
svg.selectAll('rect’) creates an empty set of rect elements.
.data(data) Adds object or array of data to be turned into elements in the DOM
.append('rect') Appends a ‘rect’ element for every item in the data
attr() statements define what we want our bars to look like. Most importantly, they can use properties from each item in the data. Before we add an axis to the graph, we’d probably need to define the start and end points.
To do that we’d use xScale to define the scale of our chart:
var xScale = d3.scale
.linear()
.domain([0, data.length])
.range([0, width]);
Tooltips
Whenever we have a data point on a plot or a chart and there’s any semblance of interactivity, we can place tooltips on our visualization to provide context.
Tooltips can let us mouse over bits of data within our chart and communicate without any other interaction. Tooltips are just chained pointer events. Here’s a simple implementation of tooltips in D3.js:
The secret to easily implementing tooltips in any visualization ultimately comes down to .on("mouseover”) and .on("mouseout”) events.
Once we have our events set up, we simply chain animation attributes and listen for the end event. The .each() method is used to detect the end of each animation. If you’ve ever used jQuery you’ll recognize D3’s method chaining as strikingly familiar.
Styles can change, attributes can be configured and elements appended by chaining methods.
Animations and Transitions
D3’s focus on transformation extends naturally to animated transitions.
Animations or Transitions as they’re known in D3 are incredibly useful for conceptualizing deltas in datasets or providing interactivity.
Transitions are described as interpolating styles and attributes that animate over time. D3 Transition methods animate DOM elements and carry them from a current state to an end state.
Transitions occur over 4 phases – transition scheduled, started, run, and ended. This “life cycle” is important to note when we use multiple animations on a single object of data. Here’s a simple example of a D3 animation:
Imagine that all transitions have a duration, Mike Bostock refers to transitions as having life and death cycles.
D3 Transitions take a selection of elements, then it applies a transition to a part of the current state of the element, for each element.
The d3.selection.transition method allows us to define what properties are changed, how the properties change, the length of time it takes for the transition to occur when the transition starts after it is triggered, and what the end state will look like.
Layouts
In D3 we utilize layout methods to encapsulate our visualizations. Layouts take data as input and remap or otherwise transform it, generating new data that is more convenient for a specific visual task. Histogram, Cluster, Pie, Stack, and Treemap layouts are just some of the layouts available.
One of the coolest applications of a layout is the Force layout. The Force layout is a kind of graph diagram where the positions of nodes are obtained by a simulation of forces. A Force layout is added as an object and with select properties. Properties define the dimensions of the visualization as well as the arrays of nodes and links. Take a look at the Force layout in action:
D3 uses this layout to create elements with forces acting on each node by all other nodes. You can configure the nodes to interact with each other based on the parsed data which would then appear as if each data node was pulling other nodes to a central point within a user-defined space.
The force layout adds some visual flash. Aside from the simple example provided, the Force layout is one of the most commonly misused parts of the D3 library. Any data visualization we create should present the data in a practical manner that is relevant and provides actual insight, not just for the sake of eye candy. Remember to use the force wisely.
Dashboard built with D3
Ever wished to wow your colleagues armed with a single framework and your developer prowess? Well in my opinion here’s the most compelling reason to start using D3, rolling your own KPI dashboard.
With D3 we’re able to combine the concepts we’ve covered above to provide an at-a-glance view of any data we feed into our dashboard.
If creating an entire dashboard based on KPIs relevant to your C-Level executives isn’t enough, at the very least D3 lets you add a “Neat!” factor to any business presentation.
D3 provides a dynamic range of visual opportunities that aren’t possible with regular HTML DOM manipulation. The framework gives us a rich toolset for graphical data transformation and efficient manipulation of documents based on that data.
The similarity to jQuery prevents us from learning proprietary API calls and affords us impressive flexibility within modern Web standards. D3 is the best JavaScript multipurpose SVG library when it comes to animation, interaction, and above all binding data to graphics.
The community is very responsive, the source code is very clean and the API is well-written.
Jscrambler
The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.
View All ArticlesMust read next
The Data Processing Holy Grail? Row vs. Columnar Databases
Columnar databases are great for processing big amounts of data quickly. Let's explore how they perform when compared with row DBs like Mongo and PSQL.
December 5, 2019 | By João Routar | 8 min read
Top 5 Biggest Data Breaches and Data Leaks
How do data breaches and data leaks happen? How extensive can their impacts be? Let's explore that and the biggest data breaches and leaks with our list.
March 10, 2021 | By Jscrambler | 9 min read