Playing With D3

Playing Around with D3.js

A Guide to Create Simple D3 Visual

"A picture is worth a thousand words. A picture can also be worth many data points (or more!)"

Traditionally data is stored in various tabular/text formats through which it becomes quite difficult to understand how it is fluctuating. But only when we plot the data into graph, we get a clear picture of how the data behaves.

Months ago, I saw a presentation on this topic and although it was a basic introduction to the far fetched capacities of d3.js, it inspired me to read about it. So that is my goal with this blog post , I hope it grabs enough of your attention for you to dip your hands dirty in some d3 code!

Starting with basic theoretical Introduction

Data Driven Documents developed by Mike Bostock is for manipulating documents based on data. In layman terms, it will provide you with an interesting visual aid to represent that large amount of boring data.Its not a new technology altogether, its just a library created on top of JavaScript, so if you have a history in scripting, you might just enjoy creating this piece of document with me. It uses familiar JavaScript conventions which are easy to follow.

D3 JavaScript library is very self-sufficient. It has no dependency on any JavaScript library than other what your browser already provides. In fact, it can even be used in a non-browser environment such as Node.js with some minimum setup. The syntax is a piece of cake if you have ever manipulated a DOM structure using JavaScript before. Dont worry, even if you haven’t, the code will be simple enough and self-explanatory.

To tag along, I highly recommend you to use a good editor like Atom or Sublime. Also you’d need this d3.js file to be included in your HTML.

But first, what is Functional Chaining?

Before you start to write the code, one thing you should be absolutely clear about is this coding style called Functional chaining, because here we’ll be using a lot of it. Without its knowledge, the code might seem pretty absurd to you. It is a technique that can be used to simplify code in scenarios that involve calling multiple functions on the same object consecutively. Its like a Unix pipeline where output of the first function is input to the next.

d3.select("body")
    .append("p")
    .text("New element!");

If this style is not your cup of tea, you can anyways try the chain-less approach like this: 

var body = d3.select("body");
var p = body.append("p");
p.text("New element!");

Lets get started:

  • Step 1: Selection:  It helps you target visual elements on the page.
d3.select("body").style("background-color", "black");

Its like telling a specific element which of its properties you’d like to manipulate.

![Selection] [logo]
  • Step 2: Binding data: Its as simple as : Input-> Data, Output-> Visual Representation. 
    Now that you have selected which element your data will be associated with, its time to map the data into visuals, and for that we first need to feed our data in.
var dataset = [ 5, 10, 15, 20, 25 ];
d3.select("body").selectAll("p")
    .data(dataset)
    .enter()
    .append("p")
    .text("New element!");

d3.select(“body”) — Looks for the body in DOM and hands a reference off to the next step in the chain.

.selectAll(“p”) — Selects all paragraphs. Since we dont have any,it will output empty selection.(Its ok, dont get confused, I'll explain this below!)

.data(dataset) — Counts and parses our data values. There are five values in our data set, so everything past this point is executed five times, once for each value.

Now the paragraphs that I’ve selected do not exist in my DOM yet. Here we are selecting the elements which dont exist yet.

What kind of sorcery is this?

The enchanted enter() method: This method looks at the DOM, and then at the data given to it. If data is more than corresponding DOM elements, then enter() creates a new element on which you may work your magic. It then hands off a reference of this new placeholder to the next step in the chain.

append() : Takes the placeholder selection created by enter() and inserts a p element into the DOM. Ta-da! The element reference is passed on further in the chain.

  • Step 3: Put that data to work!
    Lets change the last line to:
    javascript
    .attr(“height”,function(d){ return d;})

    You may be wondering why you have to write out function(d) instead of just d on its own. For example, this won’t give you the height value:
    javascript
    .attr("height" ,d);

    The reason for this syntax is that .text(), attr(), and many other D3 methods take a function as an argument. Here wrapping d in an anonymous function is necessary otherwise d will have no value.

The anonymous function is simply returning the data value, but you can make it fancier by putting your custom code in it.

For example this cool random color generator:
javascript
.attr(“fill”,function(d){
var a=Math.round(Math.random()*156)+100;
var b=Math.round(Math.random()*156)+100;
var c=Math.round(Math.random()*156)+100;
var o=Math.random()*1;
return “rgb(245,”+b+”,”+c+”)”;
});

Say Hello to SVG!

D3 is most useful when used to generate and manipulate visuals as SVGs as it is more reliable, visually consistent, and faster. Scalable Vector Graphics is a text-based image format. SVG code can be included directly within any HTML document. It is supported by almost every other modern browser.

Before you can creating anything, you must create an SVG element. Think of the SVG element as a canvas on which your visualizations are rendered.

Its a good practice to give this SVG element a defined height and width, otherwise it will take up as much room as it can within its enclosing element.

var svg = d3.select("body")
            .append("svg")
            .attr("width", 500)
            .attr("height", 50);

Lets make something from what we’ve learnt so far!

var w=600;
var h= 250;
var dataset= [50,70,100,50,200,90,60,80,30,140,70,150,50,20];
var base= d3.select('body')
            .append('svg')
            .attr('height',h)
            .attr('width',w);
var chart= base.selectAll('rect')
                .data(dataset)
                .enter()
                .append('rect')
                .attr('x',function(d,i){return i*51;})
                .attr('y',function(d){return h-d;})
                .attr('width',35)
                .attr('height',function(d,i){return d;})
                .attr("fill", function(d) {return "rgb(100, 0, " + (d * 2) + ")"; });

Click here to see how the output looks like.

Hopefully you enjoyed reading this post and tried recreating this on your own.

Leave a Reply

Your email address will not be published. Required fields are marked *