pnd
pnd

Reputation: 442

dc.js barChart first and last bar not displaying fully

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: dc.js barChart 1

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. enter image description here

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

Answers (2)

pnd
pnd

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

Austin
Austin

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

Related Questions