Reputation: 610
I'm creating a bar chart using an ordinal scale for the x axis, and using rangeRoundBands. I'm following this example: https://bl.ocks.org/mbostock/3885304
However, my chart has outer padding -- big spaces at the beginning and end of the axis, where I'd like the bars to fully extend. The screen shot below shows the spaces I'm referring to circled in red.
How can I remove these spaces? I need my margins and the svg width and height to remain the same.
Here is a Plunker with the chart as it is now: https://plnkr.co/edit/gMw7jvieKSlFbHLTNY9o?p=preview
Code is also below:
<!doctype html>
<html>
<head>
<style>
.axis path{
fill: none;
stroke: #cccccc;
stroke-width: 2px;
}
.x.axis text{
display:none;
}
.bar{
fill: blue;
}
body{
font-family:Helvetica, Arial, sans-serif;
}
</style>
</head>
<body>
<div id="barchart"></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 0, bottom: 50, left: 300},
width = 800 - margin.left - margin.right;
height = 465 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .5);
var y = d3.scale.linear().range([height, 0]);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom");
var barsvg = d3.select("#barchart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "barchartbox")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.json("population.json", function(error, data1) {
x.domain(data1.map(function(d) { return d.country; }));
y.domain([0, d3.max(data1, function(d) { return d.value; })]);
barsvg.selectAll(".axis").remove();
// Add the Y Axis
barsvg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Add the X Axis
barsvg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var bars = barsvg.selectAll(".bar")
.data(data1);
bars.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.country); })
.attr("width", x.rangeBand())
.attr("y", function(d) {return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
bars.exit().remove();
});
</script>
</body>
</html>
Upvotes: 4
Views: 3924
Reputation: 32327
You doing.
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .5);
Instead use rangeBands.
var x = d3.scale.ordinal()
.rangeBands([0, width], .5);
working code here
Upvotes: 7
Reputation: 14589
It is specified in the d3 document that while using rangeRoundBands, rounding introduces additional outer padding which is, on average, proportional to the length of the domain.
For example, for a domain of size 50, an additional 25px of outer padding on either side may be required. Modifying the range extent to be closer to a multiple of the domain length may reduce the additional padding.
Reference: rangeRoundBands
So the solution would be to use following lines after setting the x axis domain:
var mult = Math.max (1, Math.floor (width / x.domain().length));
x.rangeRoundBands ([0, (x.domain().length * mult)], 0.1, 0);
Upvotes: 3