Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force nvd3 to display the equal number of ticks as that of the values plotted on the graph-nvd3

How can force nvd3 graph to have certain number of ticks to be displayed, for example, please find below the image of the graph plotted: enter image description here

as seen below I have 7 values pushed to the array holding the 7 days of the week. However looks like they have more number of ticks than the actual values. What I'm looking for is something similar to this:http://nvd3.org/examples/line.html However when i hover over these ticks they are misaligned as shown: enter image description here

thats where the graph line should be and thats where the hovered tick shows the tooltip.but for some reason i dont get 7 ticks displayed instead gets 10 ticks displayed and all the hovered tooltips get misaligned.I also tried to force nvd3 to have specific # of ticks but didnt work.

                chart2.xAxis
                .ticks(7)
                .tickFormat(function(d) {
                    return d3.time.format.utc('%b %d')(new Date(d));
                });

here is the fiddle: http://jsfiddle.net/86hr7h1s/4/ I should ideally display 7 days and 7 ticks on the graph as oppose to duplicate days and 10 ticks on the graph. Any ideas whats wrong and how to correct this?

EDIT::::::

I was able to fix my issue for 7 days with the below answer, using the tickValues() instead of ticks(). However, for large values, say display a graph data of 2 months, i'll have 30 data points. I still see that my graph ticks on hover dont align:

enter image description here

As you can see above the hover points still dont align with the vertical ticks. I dont want to force the ticksValues for more than 7 days on the graph. Ay ideas how this could be achieved?

FYI: I used this to make nvd3 display 7 values:

    var datas = this.graphFunction(data);
    chart2.xAxis.tickValues(datas[0].xAxisTickValues);

http://jsfiddle.net/86hr7h1s/5/

Thanks!

like image 839
user1234 Avatar asked Aug 31 '15 23:08

user1234


2 Answers

If you want to control the ticks precisely, you should use .tickValues() rather than ticks().

API Doc

like image 127
huan feng Avatar answered Nov 08 '22 10:11

huan feng


I understand that the question was asked a long time ago, but I recently faced the same issue and found a good solution for it.

The reason of the issue with inaccurate ticks on the x-axis is the inaccurate internal numeric representation of dates that we want to display on the x-axis. As we can see here https://nvd3.org/examples/line.html when values on the x-axis are numbers, all ticks are displayed accurately. When we want to display dates on the x-axis, we also need to convert dates to some numeric representation. Typically dates are converted to the numeric representation via the Date.prototype.getTime() function and then labels are formatted using a code like this chart.xAxis.tickFormat(d3.time.format('%b %Y')(date)) But the accuracy which the getTime() function provides to us is redundant in most cases. Assume we want to display only months and years on the x-axis and have a sorted list of dates where different items always have different moths but the item with a particular month may have any day and time. So, there may be a situation, where two adjacent list items have though have different months are very close to each other (for example, "Feb 28" and "Mar 1"). When we convert these list items to numeric representation using the getTime() function, the resulting list of big numbers remembers how far adjacent list items stand apart from each other. As the distance between adjacent chart points is always equal in NVD3 charts, NVD3 tries to fine-tune labels display to provide the info that some numbers are close to each other, but others are not. It leads to inaccurately displayed labels or even to duplicated labels if a chart has few points.

The solution is to omit redundant information about date and time when we convert dates to numbers. I needed to display only months and years on the x-axis and this code works great for me.

function getChartData(data) {
  var values = data.map(function(val) {
    return {
        x: val.x.getUTCFullYear() * 12 + val.x.getUTCMonth(),
        y: val.y
      }
  });

  return [{
    values: values,
    key: 'date'
  }];
}

function formatDate(numericValue) {
  var year = Math.floor(numericValue / 12);
  var month = numericValue % 12;
  return shortMonthNames[month] + ' ' + year;
}
    
nv.addGraph(function() {
  var data = [
   ...
    {
      x: new Date(2020, 2, 15, 15, 12),
      y: 90
    },
    {
      x: new Date(2020, 3, 3, 3, 54),
      y: 50
    },
    ...
  ];
  
  var chart2 = nv.models.lineChart()
  .showXAxis(true)
  .showYAxis(true);
  
  chart2.xAxis.tickFormat(formatDate);
  
  d3.select('svg#svg')
  .datum(getChartData(data))
  .call(chart2);
  
  return chart2;
});

Here we don't use the .tickValues() NVD3 function and so don't interfere to the default rendering engine, so the NVD3 lib can automatically add or remove axis labels when the viewport width is changed, and ticks and corresponding vertical lines are displayed exactly on the place where they should be.

Here is the full working example http://jsfiddle.net/AlexLukin/0ra43td5/48/

like image 30
Alex Lukin Avatar answered Nov 08 '22 12:11

Alex Lukin