Introducing D3. A simple example - D3 on AngularJS: Create Dynamic Visualizations with AngularJS (2014)

D3 on AngularJS: Create Dynamic Visualizations with AngularJS (2014)

Introducing D3. A simple example

In this chapter, we’ll go over what D3 is and what makes it such a powerful tool for data visualization. We’ll also introduce a simple ‘Hello World’ style example that shows how to get quickly get setup and running with D3.

What is it?

D3 (or Data-Driven Documents) is a library written by Mike Bostock for “manipulating documents based on data.” This means D3’s primary job is to take data and produce structured documents such as HTML or SVG with respect to data. Unlike most visualization libraries, D3 is not a ready-made collection of common graphs and widgets. It’s common to use D3 to make common graphs, like bar charts and pie charts, but the real power is in its flexibility and fine grain control over the final result.

D3 works well with other established web technologies like CSS and SVG because it doesn’t attempt to abstract away the DOM, like many other graphing libraries. This also means D3 will continue to be useful as browsers incorporate new features.

If we’re just looking for a particular graph type, say, a bar chart, and don’t care how exactly it ends up looking, D3 might not be the right library for the job. Several other ready-made libraries exist for creating simple, cookie-cutter charts, such as HighCharts or Chart.js or Google Charts API. If, on the other hand, we have strong requirements for how our visualization should look and function, D3 is a great choice.

To quickly jump into a real world example of this, take the following interactive visualization produced by KQED’s the Lowdown blog. It doesn’t fall into a single, chart category and the different chart components need to communicate with each other, updating dynamically.

error

Live version of the above interactive visualization

It was created using a combination of Angular and D3. (source code is available here).

To illustrate this point, we’ll also walk though a little thought experiment. Imagine we’re working with a ready-made visualization library. Typical visualization libraries might have a BarChart class to create a new bar chart which works fine until we want to do something the library didn’t allow to be configured. For example, say we wanted to change the background color of the legend in our bar chart. We could take their code and try and modify it to add our needed feature, but that can quickly get very messy and cumbersome. We might have to create a new subclass of theBarChart or it could be that the original BarChart class wasn’t written in a way to be easily extensible. Alternatively, we can use D3 to quickly, and only in a few lines, create our own custom bar chart were we can do whatever we’d like to our legend or any other component.

As another example, say we wanted to create a new type of visualization that doesn’t even exist yet (or at least not yet in JavaScript.) This is a perfect example of when we would want to use D3. In this sense, D3 is a sort of “meta-library”; the kind of library one would want to have if they were creating a library of new data visualizations. It does this by using a new way of thinking about data visualizations (but more on that, later.) In short, if we’re going to be creating data visualizations, we’ll typically be writing an order of magnitude less code if we use D3 than without.

When it comes to configuring the look and feel our visualization, we can very easily utilize our existing knowledge of CSS, so long as we use classes when creating the components that make up our bar chart. Continuing our though experiment, something along these lines would be enough to change the background color of our legend.

1 .graph .legend{

2 color: white;

3 }

D3’s functional, declarative style permits us to write less code. Less code allows us to make changes faster and reduces the cognitive load required to remember all the code we’ve written. When code is shorter, we can remember it better and read if faster, later.

Consider the following example that changes all <circle> nodes in an <svg> to be positioned horizontally occurring to the data array.

tip

Don’t worry if this is confusing right now. We’ll walk through how this works in later chapters. This sample is only to demonstrate D3’s brevity.

Using straight JavaScript, we’ll need to select the <svg> element and select all of the <circle> elements (assuming they are on the DOM already) and modify their cx attribute, like so:

1 var data = [ 10, 20, 30, 40];

2 var svg = document

3 .getElementsByTagName('svg')

4 .item(0);

5 var circles = svg.getElementsByTagName('circle');

6 for(var i = 0; i < circles.length; i++){

7 var circle = circles.item(i);

8 circle.setAttribute('cx', data[i]);

9 }

Using D3 allows us to accomplish the same using less code:

1 d3.select('svg').selectAll('circle')

2 .data([10, 20, 30, 40])

3 .attr('cx', function(d){ return d; });

‘Hello World’ D3 style

To dive right in, bellow is a simple ‘Hello World’ style D3 example which simply appends an <h1> with the text Hello World! to the <body> using D3.

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

5 </head>

6 <body>

7 <script>

8 d3.select('body')

9 .append('h1')

10 .text('Hello World!');

11 </script>

12 </body>

13 </html>

error

Live version: http://jsbin.com/uhEmuJI/1/edit

We just created our first D3 app.

Although this example does not do very much, it highlights the structure we’ll build with our D3 apps; the foundation for most of the examples that follow.

The resulting HTML after our D3 code has executed looks like this.

1 <html>

2 <head>...</head>

3 <body>

4 <script>...</script>

5 <h1>Hello World!</h1>

6 </body>

7 </html>

tip

We can inspect the source of the resulting HTML using the fantastic Chrome developer tools Elements tab. We’ll use these tools throughout the book to deeply inspect our running code.

warning

Common Gotcha

When not using Angular or jQuery, make sure to put any code that depends on the <body> inside the <body> and not before it (ie., in the <head>.) If the code executes before the body element, then it will simply fail as the <body>