Let's say you have a d3.js scale as so (we're assuming horizontal bar chart here)
var yScale = d3.scale.ordinal()
.rangeRoundBands([0,height]); //height of chart
A common way to then create bars is to append rects to your svg. Below is some common sample code. I've excluded various other attributes in order to just focus on y
and height
:
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("y", function(d) { return yScale(d); })
.attr("height", yScale.rangeBand());
However, for graphs of just 2-3 elements, it causes each band to be very large. I want to enable a 'maxBarHeight' stipulation, but I'm having trouble ensuring that the bar is always centered on the ordinal. This is what I have so far:
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("y", function(d) {
if(yScale.rangeBand() > maxBarHeight)
return yScale(d) + (maxBarHeight / 2); //This doesn't work
else
return yScale(d);
})
.attr("height", (yScale.rangeBand() > maxBarHeight ? maxBarHeight : yScale.rangeBand()))
Is there a simpler way to control bar size while maintaining alignment?
I've found the best way to control bar size and centering is to not mess around with the x/y or width/height attributes of the rect
, but to instead use the padding parameters in rangeBands()
or rangeRoundBands()
. Below are some example charts plotting gender data:
var yScale = d3.scale.ordinal().rangeRoundBands([0,chartHeight]);
var yScale = d3.scale.ordinal().rangeRoundBands([0,chartHeight],.7);
var yScale = d3.scale.ordinal().rangeRoundBands([0,chartHeight],.5,.1);
This method will let you adjust the bar size while maintaining alignment with the ordinal.