Show Buttons
Share On Facebook
Share On Twitter
Share On Google Plus
Share On Linkdin
Share On Reddit
Share On Stumbleupon
Contact us
Hide Buttons

d3 Fundamentals: Creating a simple bar graph

null

After learn­nig about how data bind­ing takes place in d3 along with its notion of domains, ranges and scales, we are going to con­tinue our data visu­al­iza­tion series with the sim­plest exam­ple pos­si­ble — cre­at­ing a rec­tan­gle — and then we go on to cre­ate some­thing more mean­ing­ful — a bar chart.

So, whats in a rectangle?

Rec­tan­gles are native to the svg spec­i­fi­ca­tion like cir­cles and groups and many other ele­ments. A rec­tan­gle has a cou­ple of attrib­utes that are used to ren­der it on an svg — x, y, width and height.

We will start out this arti­cle by tak­ing just one data point and then try to draw a rec­tan­gle for that data point. Then, we will build upon the same con­cept and the stuff we learned in our pre­vi­ous posts to draw mul­ti­ple rec­tan­gles in order to cre­ate our bar graph.


TIP: When work­ing with svgs, hav­ing a cheat­sheet of the var­i­ous attrib­utes of the valid svg ele­ments can go a long way in help­ing you become more pro­duc­tive. You can find a really good one over here.


Draw­ing a rec­tan­gle itself in SVG is pretty sim­ple. All you gotta do is spec­ify the val­ues of each of its attrib­utes and you’re good to go.

var chart = d3.select('.chart');
var bar = chart.append('g');
bar.append('rect')
  .attr('width', 20)
  .attr('height', 50);

You can get your hands dirty with these val­ues in this jsfid­dle.

In the above code, you can see that we sim­ply cre­ated a rec­tan­gle with a width of 20px and a height of 50 px. If now spec­i­fied, x and y take up their default val­ues of 0.

Also notice that we added our rec­tan­gled with a ‘g’ tag. This is help­ful when you later want to add labels to your rec­tan­gle as it makes makes it eas­ier to rel­a­tively posi­tion the label text within the groups.

Draw­ing our bar chart

Assume that we want to plot a bar chart of the age of a few peo­ple and the data is avail­able in an array as follows

var ages = [30, 22, 33, 45];

Lets say tht we choose to rep­re­sent the length of the bars on the y axis.
We first start by defin­ing the func­tions that will be used as converters.

var totalWidth = 500;
var totalHeight = 200;
var scale = {
  y: d3.scale.linear()
};

Assum­ing that a per­son lives a max of 100 years and starts at 0 years, we can safely define our domain as follows.

scale.y.domain([0, 100]);

Now lets say that you want to draw this on an area of size 200x400px. Since we are only con­cerned about the height, thats all we will need to define our range.

scale.y.range([0, 200]);

To actu­ally plot this data on the graph, we will need to do two things.
1. Cre­ate as many group nodes on the svg as there are ele­ments in our array and bind them to the data.

  • Cre­ate a rec­tan­gle inside of each group node.
  • For each rec­tan­gle, use its cor­re­spond­ing data point to deter­mine its scaled height on the draw­ing area

Append­ing the bars and adding nodes can be done as shown below. If you are’nt sure about how things are work­ing, I sug­gest you quickly breeze through our arti­cle on selec­tions before you proceed.

var chart = d3.select('.chart')
    .attr({
        'width': totalWidth,
        'height': totalHeight
    });

var bars = chart
    .selectAll('g')
    .data(ages)
    .enter()
    .append('g');

Now, lets add a rec­tan­gle to each of these ‘g’ tags and use the ‘inher­ited’ data to spec­ify the dimen­tions of the rect.


TIP : When you add child nodes to a node to which data is already bound, it inher­its the data from its parent.


bars.append('rect')
    .attr({
        'x': function (d, i) {
            return i * barWidth;
        },
        'width': barWidth - 1,
        'height': scale.y
    });

There are a few key points to observe about the above code

  • Ear­lier we said that we wanted to append a rect to each bar(‘g’ node) but as seen above, there isi’nt a loop of any kind to do that. Since the result of the pre­vi­ous oper­a­tion resulted in the vari­able ‘bars’ to ref­er­ence a num­ber of ele­ments after data bind­ing and append, d3 auto­mat­i­cally iter­ated over each of the bars and appended a ‘rect’ node to each of them.
  • The value of the vari­able ‘height’ is spec­i­fied as scale.y. One has to remem­ber that scale.y is actu­ally a func­tion that takes an argu­ment and returnes a scaled value. In this case, scale.y will receive the data point as the argu­ment and scale it for each node. In fact, the above code is just a short­hand for the following
bars.append('rect')
    .attr({
        'x': function (d, i) {
            return i * barWidth;
        },
        'width': barWidth - 1,
        'height': function (d, i) {
            return scale.y(d);
        }
    });

The full source code of the exam­ple so far can be found in this jsfid­dle.


Turn­ing it up

You must have noticed that the bar chart that we just drew appears inverted. Thats because in SVG, the top left is con­sid­ered to be the ori­gin — aka (x=0, y-0). While this works well for the com­puter, its doesnt really work that well for us.

There­fore in most graphs that you draw which need to be pre­sented bottom(s)-up, you’d need to alter the scale func­tions for the y axis to pro­duce the cor­rect output.

In order to fix the bar graph in our exam­ple, we need to do two things

  • Invert the array that rep­re­sents the range of y. This will cause a smaller val­ues of y to be drawn lower on the chart and vice versa.
  • Start draw­ing the rec­tan­gle from the y value gen­er­ated upto the max­Height. i.e. height of rect = Total height — Y value.
// ...
// ...
scale.y.range([totalHeight, 0]);
// ...
// ...
bars.append('rect')
    .attr({
        'x': function (d, i) {
            return i * barWidth;
        },
        'y': scale.y,
        'height': function (d) {
            // This is how much height is left over after
            // applying the inverted scale for the y axis
            return totalHeight - scale.y(d);
        },
        'width': barWidth - 1
    });

The full source code for this exam­ple can be found in this jsfid­dle.


In the next post, we will learn how to add an x and y axis to our graph and add a very basic hover state to bars.

Fol­low us on twit­ter to get the next arti­cle the moment it gets freshly baked out of our oven.


Ryan Sukale

Ryan is just a regular guy next door trying to manage his life and finances.

You may also like...