Neeraj Sharma Neeraj Sharma - 3 months ago 85
jQuery Question

Horizontal Bar chart using d3 js

I am using d3.js for plotting a bar chart. I want to show bar chart between two input values but in form of string values instead of integer values in x-axis.

An example of what I am trying to achive

var y-axis= ['Accessories', 'Audiophile', 'Camera & Photo', 'Cell Phones', 'Computers','eBook Readers'];

var x-axis= ['development', 'design', 'testing', 'UAT', 'LiveDeployment'];

Reference url which I have used is D3 js simple horizontal bar chart

Code is below :

data = [
{label:"Category 1", value:25},
{label:"Category 2", value:50},
{label:"Category 3", value:100},
{label:"Category 4", value:75},
{label:"Category 5", value:40},
{label:"Category 6", value:20}
];

var axisMargin = 10,
margin = 20,
valueMargin = 2,
width = parseInt(d3.select('#barchart').style('width'), 9),
height = parseInt(d3.select('body').style('height'), 9),
barHeight = 23, //(height-axisMargin-margin*2)* 0.6/data.length,
barPadding = (height-axisMargin-margin*2)*0.4/data.length,
data, bar, svg, scale, scale2, xAxis, labelWidth = 0;

max = d3.max(data, function(d) { return d.value; });

svg = d3.select('#barchart')
.append("svg")
.attr("width", width)
.attr("height", height);

bar = svg.selectAll("g")
.data(data)
.enter()
.append("g");

bar.attr("class", "bar")
.attr("cx",0)
.attr("transform", function(d, i) {
return "translate(" + margin + "," + (i * (barHeight + barPadding) + barPadding) + ")";
});

bar.append("text")
.attr("class", "label")
.attr("y", barHeight / 2)
.attr("dy", ".35em") //vertical align middle
.text(function(d){
return d.label;
}).each(function() {
labelWidth = 125; //Math.ceil(Math.max(labelWidth, this.getBBox().width));
});


scale = d3.scale.linear()
.domain([0, max])
.range([0, width - margin*2 - labelWidth]);

var scale2 = d3.scale.ordinal()
.domain(["01/01/2016 Production Start Date", "01/01/2016 Production End Date", "Transcoding", "Encryption", "Published", "Published Release Date"])
.rangePoints([0, width - margin*2 - labelWidth]);

var xAxis = d3.svg.axis()
.scale(scale2)
.tickSize(-height + 2*margin + axisMargin)
.orient("bottom");

bar.append("rect")
.attr("transform", "translate("+labelWidth+", 0)")
.attr("height", barHeight)
.attr("width", function(d){
return scale(d.value);
});

bar.append("text")
.attr("class", "value")
.attr("y", barHeight / 2)
.attr("dx", -valueMargin + labelWidth) //margin right
.attr("dy", ".35em") //vertical align middle
.attr("text-anchor", "end")
.text(function(d){
return (d.value+"%");
})
.attr("x", function(d){
var width = this.getBBox().width;
return Math.max(width + valueMargin, scale(d.value));
});

svg.insert("g",":first-child")
.attr("class", "axisHorizontal")
.attr("transform", "translate(" + (margin + labelWidth) + ","+ (height - axisMargin - margin)+")")
.call(xAxis);


How can I :
1) Show x-axis lines in above code
2) X-Axis text are of large size (01/01/2016 Production Start Date) so I need to break it into two lines.

Answer

You certainly can format the ticks, but there is an easy workaround: create another scale just for the ticks, and call this alternative scale for your x axis:

var xScaleString = d3.scale.ordinal()
      .domain(["design", "development", "testing", "UAT"])
      .rangePoints([0, width]);

The advantage of using this unusual approach is that you can spread the strings along the x axis the way you want. The disadvantage is that you may not have a perfect match regarding the values of your original scale (10, 20, 30 etc).

Remember to keep your original scale (it's the one used for the rectangles).

Comments