Reputation: 703
I want to create a barchart displaying C02 emission.
The Problem (see picture below):
Why are the bars "pushed" to the right? Why are the years in the x-axis displayed without the first integer?
I am using Version 3 of d3.
Given some JSON data like this:
[
{
"Cement": 0.0,
"Gas Flaring": 0.0,
"Gas Fuel": 0.0,
"Liquid Fuel": 0.0,
"Per Capita": null,
"Solid Fuel": 3.0,
"Total": 3.0,
"Year": 1751
},
and so on…
]
To prepare for scaling I did:
var minDate = dataset[0].Year;
var maxDate = dataset[dataset.length - 1].Year;
var maxValue = d3.max(dataset, function(d) {
return d["Per Capita"];
});
I append the svg
var svg = d3
.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
I sacled the xAxis and the yAxis:
var xAxisScale = d3.time
.scale()
.domain([minDate, maxDate])
.range([0, w]);
var yAxisScale = d3.scale
.linear()
.domain([0, maxValue])
.range([h, 0]);
The I finally builded these axisses…
var xAxis = d3.svg
.axis()
.scale(xAxisScale)
.orient("bottom");
var yAxis = d3.svg
.axis()
.scale(yAxisScale)
.orient("left");
svg
.append("g")
.attr("class", "axis")
.attr("transform", "translate(92," + (h - padding) + ")")
.call(xAxis);
svg
.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",-90)")
.call(yAxis);
I also than addeded the rects…
svg
.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.style("fill", "teal")
.attr({
x: function(d, i) {
return i * (w / dataset.length);
},
y: function(d) {
return yAxisScale(d["Per Capita"]);
},
width: w / dataset.length,
height: function(d) {
return h - yAxisScale(d["Per Capita"]);
}
});
The result is not the intended one.
Could you please elaborate what went wrong?
Why are the bars "pushed" to the right? Why are the years in the x-axis displayed without the first integer?
I am using Version 3 of d3.
Thank you very much!
Upvotes: 1
Views: 41
Reputation: 102194
The main problem here is that this...
"Year": 1751
... is not a date object. That's just a number. If you look at your axis you'll realise that.
So, you have to parse it. For instance:
const format = d3.time.format("%Y");
dataset.forEach(function(d){
d.Year = format.parse(d.Year);
});
Also, when you do this...
var minDate = dataset[0].Year;
var maxDate = dataset[dataset.length - 1].Year;
... you're blindly trusting that the array is sorted. Don't do that. Instead, do:
var minDate = d3.max(dataset, function(d){
return d.Year
});
var maxDate = d3.min(dataset, function(d){
return d.Year
});
Or, if you want to use destructuring:
var [minDate, maxDate] = d3.extent(dataset, d => d.Year);
Finally, now that you have a proper scale, don't use the indices for the x
position. Use the scale:
x: function(d) {
return xAxisScale(d.Year);
},
This covers the problem regarding the x
position. For fixing the y
position, just set a proper margin.
Upvotes: 1