Reputation: 442
I have a barChart with a d3.time.scale
x-axis. I am displaying some data per hour, but the first and last data point bars are always cut in half when using centerBar(true)
.
(When using centerBar(false)
the last bar disappears completely.)
The time window is based upon the data itself and is calculated as follows:
var minDate = dateDim.bottom(1)[0]["timestamp"];
var maxDate = dateDim.top(1)[0]["timestamp"];
.x(d3.time.scale().domain([minDate, maxDate]));
The last line sets the time scale domain to use min and maxDate. This is how it looks:
I have increased the bar width slightly using .xUnits(function(){return 60;})
as the default is so thin that the first bar disappears within the y-axis.
Also I already tried to change the domain by substracting/adding one hour to min/maxDate, but this results in unexpected behaviour of the first bar.
I used the following to calculate the offset:
minDate.setHours(minDate.getHours() - 1);
maxDate.setHours(maxDate.getHours() + 1);
Is there a fix or workaround for this to add padding before the first and after the last bar?
Upvotes: 5
Views: 1287
Reputation: 442
The mistake was not realising JavaScript's passing-by-reference when using objects such as Date objects.
In addition to Austin's answer, which did solve the problem by using d3 functionality, I investigated why my initial attempt by modifying the minDate
and maxDate
variables failed.
The problem is that when creating the variables
var minDate = dateDim.bottom(1)[0]["timestamp"];
var maxDate = dateDim.top(1)[0]["timestamp"];
I created pointers to the actual data instead of creating new objects with the same value as the minDate
and maxDate
objects. The line
minDate.setHours(minDate.getHours() - 1);
therefore then manipulated the actual underlying data within the date dimension dateDim
, which then led to the peculiar behaviour.
The obvious solution would have been to create new Date()
objects like this:
var minDate = new Date(dateDim.bottom(1)[0]["timestamp"]); var maxDate = new Date(dateDim.top(1)[0]["timestamp"]);
and then do the desired manipulations:
minDate.setHours(minDate.getHours() - 1); maxDate.setHours(maxDate.getHours() + 1);
Upvotes: 3
Reputation: 6709
Subtract an hour from the minDate and add an hour to the maxDate to get an hour worth of padding on each side of your min and max data.
The trick here is to use d3.time.hour.offset and play with offsets until it looks nice.
.x(d3.time.scale().domain([d3.time.hour.offset(minDate, -1), d3.time.hour.offset(maxDate, 2)])); `
See this fiddle http://jsfiddle.net/austinlyons/ujdxhd27/3/
Upvotes: 6