The x axis likes to repeat dates when there are a limited number of dates. Please see this fiddle:
http://jsfiddle.net/skilesare/bFfJ2/1/
nv.addGraph(function() {
var data = fakeActivityByDate();
var chart = nv.models.lineChart();
chart.xAxis
.axisLabel('Date')
.rotateLabels(-45)
.tickFormat(function(d) { return d3.time.format('%b %d')(new Date(d)); });
chart.yAxis
.axisLabel('Activity')
.tickFormat(d3.format('d'));
d3.select('#chart svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(function() { d3.select('#chart svg').call(chart) });
return chart;
});
function days(num) {
return num*60*60*1000*24
}
/**************************************
* Simple test data generator
*/
function fakeActivityByDate() {
var lineData = [];
var y=0;
var start_date = new Date() - days(365); // one year ago
for (var i = 0; i < 4; i++) {
lineData.push({x: new Date(start_date + days(i)), y: y});
y=y+Math.floor((Math.random()*10)-3);
}
return [
{
values: lineData,
key: 'Activity',
color: '#ff7f0e'
}
];
}`
If your screen is wide enough you will see dates repeated. If you sqeeze the window, the problem goes away.
The problem is not related to screen size as it might appear also for cases like this: you have just 3 days to display and instead of 3 ticks you will get 6 or 10 or whatever (actually that's precisely the case you're in if I look at your jsfiddle). It is true that nvd3 uses something like this to set the dimensions of the ticks (take a look at axis.js):
if (ticks !== null)
axis.ticks(ticks);
else if (axis.orient() == 'top' || axis.orient() == 'bottom')
axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);
There are several solutions to this problem:
you either implement your own axis component and replace the nvd3's axis
you either modify the nvd3's axis component directly and add some settings that would then be used specifically for this scenario you are describing (you will notice that as it is nvd3 is highly customizable).
Hack: you use d3's own tickValues() and pass it an array with the dates you want to have on the screen (example: first date, last date and several dates in between calculated by your algorithm). See d3's documentation: https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-tickValues. Depending on the case (which axis you want to modify and which chart) you not only need to comment the code I pasted you and add your algorithm for setting the tickValues to the chart component (lineChart for example) but also you will need to add a setter for tickValues and overwrite the values with your values.
A late reply , but might be useful to others. I use a workaround to eliminate duplicate ticks, by maintaining an array of already applied ticks & d3's multi format specifier.
uniqueTicks = [];
xTickFormat = d3.time.format.multi([
["%Y", function (d) {
// If tick not applied yet
if (uniqueTicks.indexOf(d.getFullYear()) === -1) {
uniqueTicks.push(d.getFullYear());
return true;
} else {
return false;
}
}],
["", function () {
return true;
}]
]);
d3.svg.axis().tickFormat(xTickFormat );
This trick can be tweaked for any other type of tick format.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With