bar.js | |
|---|---|
| | |
| Data array | var data = [{"label":"1990", "value":16},
{"label":"1991", "value":56},
{"label":"1992", "value":7},
{"label":"1993", "value":77},
{"label":"1994", "value":22},
{"label":"1995", "value":16},
]; |
| Maximum value we will plot to | var data_max = 80, |
| Number of tickmarks to use | num_ticks = 5, |
| Chart margins | left_margin = 60,
right_margin = 60,
top_margin = 30,
bottom_margin = 0; |
| Set some default values like width and height | var w = 500,
h = 700,
color = function(id) { return '#00b3dc' }; |
| Setup scales for mapping our data to pixels The X scale will be linear for the width of the bars | var x = d3.scale.linear() |
| Input to this scale will be our data. | .domain([0, data_max]) |
| Output of this scale will be from 0 to the width of the graph | .range([0, w - ( left_margin + right_margin ) ]), |
| The Y scale will be for the placement of the bars in regular intervals | y = d3.scale.ordinal() |
| Input to this scale will be an index into the data array | .domain(d3.range(data.length)) |
| Output of this scale is a pixel valule. See docs for description of the padding parameter: https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands | .rangeBands([bottom_margin, h - top_margin], .5); |
| The top of our chart is actually at the bottom of the screen because of SVG's 0,0 origin being in the top left of the screen. | var chart_top = h - y.rangeBand()/2 - top_margin;
var chart_bottom = bottom_margin + y.rangeBand()/2;
var chart_left = left_margin;
var chart_right = w - right_margin; |
| Setup the SVG element and position it. | var vis = d3.select("body")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("id", "barchart")
.attr("class", "barchart") |
| Create tick marks along the axes. | var rules = vis.selectAll("g.rule") |
| generate ticks using the x scale | .data(x.ticks(num_ticks)) |
| create a group element for each tick | .enter()
.append("svg:g") |
| Move the ticks into position by translating each one the appropriate amount. | .attr("transform", function(d)
{
return "translate(" + (chart_left + x(d)) + ")";}); |
| Draw a small line for the tick. | rules.append("svg:line")
.attr("class", "tick")
.attr("y1", chart_top)
.attr("y2", chart_top + 4)
.attr("stroke", "black"); |
| Label the tick with its value. | rules.append("svg:text")
.attr("class", "tick_label")
.attr("text-anchor", "middle")
.attr("y", chart_top)
.text(function(d)
{
return d;
}); |
| Move the tick label down slightly by calculating how big it is. | var bbox = vis.selectAll(".tick_label").node().getBBox();
vis.selectAll(".tick_label")
.attr("transform", function(d)
{ |
| This translation accounts for changes in font size (through styling). | return "translate(0," + (bbox.height) + ")";
}); |
| Create the groups that will hold each bar | var bars = vis.selectAll("g.bar")
.data(data) |
| This creates one bar for each entry in our data array. | .enter()
.append("svg:g")
.attr("class", "bar") |
| We place each bar along the y axis using the ordinal scale defined above. | .attr("transform", function(d, i) {
return "translate(0, " + y(i) + ")"; }); |
| Create the actual bars | bars.append("svg:rect")
.attr("x", right_margin) |
| The width of each bar is determined by each data entry's value. | .attr("width", function(d) {
return (x(d.value));
}) |
| The height of each bar is determined by the rangeband. | .attr("height", y.rangeBand())
.attr("fill", color(0))
.attr("stroke", color(0)); |
| Generate labels for each bar. The bars are selected and appended to according to their data. | var labels = vis.selectAll("g.bar")
.append("svg:text")
.attr("class", "label")
.attr("x", 0)
.attr("text-anchor", "right")
.text(function(d) {
return d.label;
}); |
| Use the dimensions of the label to center it properly. | var bbox = labels.node().getBBox();
vis.selectAll(".label")
.attr("transform", function(d) {
return "translate(0, " + (y.rangeBand()/2 + bbox.height/4) + ")";
}); |
| Create labels showing the value of each bar to the right of it | labels = vis.selectAll("g.bar")
.append("svg:text")
.attr("class", "value")
.attr("x", function(d)
{
return x(d.value) + right_margin + 10;
})
.attr("text-anchor", "left")
.text(function(d)
{
return "" + d.value + "%";
}); |
| Recenter the value labels. | bbox = labels.node().getBBox();
vis.selectAll(".value")
.attr("transform", function(d)
{
return "translate(0, " + (y.rangeBand()/2 + bbox.height/4) + ")";
}); |
| Draw axes along the top and bottom of the graph. | vis.append("svg:line")
.attr("class", "axes")
.attr("x1", chart_left)
.attr("x2", chart_left)
.attr("y1", chart_bottom)
.attr("y2", chart_top)
.attr("stroke", "black");
vis.append("svg:line")
.attr("class", "axes")
.attr("x1", chart_left)
.attr("x2", chart_right)
.attr("y1", chart_top)
.attr("y2", chart_top)
.attr("stroke", "black");
|