javascript x 轴上的 d3.js nvd3 日期:仅显示一些日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21316617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 20:38:26  来源:igfitidea点击:

d3.js nvd3 date on x axis: only some dates are show

javascriptdated3.jsnvd3.js

提问by tobib_

I have a strange issue with showing dates on a xAxis. I am generating data like this:

我在 xAxis 上显示日期有一个奇怪的问题。我正在生成这样的数据:

for (i=0;i<12;i++){
    date=new Date(2013,i,1);

    ideas.values[i] = {"y" : Math.round(2*i*getRandom(1,2)), "x": date};
}

In my lineChart I want to create the x-axis like this:

在我的 lineChart 中,我想像这样创建 x 轴:

chart.xAxis.tickSize(12)            
           .tickFormat(function(d) {         
             var date = new Date(d);
             testarr.push(date);
             return d3.time.format('%b %y')(date);
            });

Now if I look at the chart, there are only a few Dates visible. This is why I created the array "testarr" for degbugging issues. The content of testarr is 8 Dates instead of 12 (i generated 12)

现在,如果我查看图表,只有几个日期可见。这就是我为调试问题创建数组“testarr”的原因。testarr 的内容是 8 个日期而不是 12 个(我生成了 12 个)

Now the even more strange thing: Putting the exactly same data in an MultiBarChart and using the EXACT same chart.xAxis.... function, the test arrays content are 12 values

现在更奇怪的是:将完全相同的数据放入 MultiBarChart 并使用完全相同的 chart.xAxis.... 函数,测试数组内容为 12 个值

I am speechless and hope that someone can help me out.

我无语了,希望有人可以帮助我。

Thank you guys!

感谢你们!

Complete Code below:

完整代码如下:

for lineChart: lineChart Result

对于 lineChart:lineChart 结果

<script>
var chart;
nv.addGraph(function() {
  chart = nv.models.lineChart()
  .options({
    margin: {left: 100, bottom: 100},
    //x: function(d,i) { return i},
    showXAxis: true,
    showYAxis: true,
    transitionDuration: 250
  })
  ;
  chart.xAxis.tickSize(12)            
                  .tickFormat(function(d) {         
         var date = new Date(d);
          return d3.time.format('%b %y')(date);
                 });

    chart.yAxis
       .axisLabel('y axis')
       .tickFormat(d3.format(''))
       .axisLabelDistance(50);

  d3.select('#chart1 svg')
    .datum(dataForChart)
    .call(chart);

  //TODO: Figure out a good way to do this automatically
  nv.utils.windowResize(chart.update);
  //nv.utils.windowResize(function() { d3.select('#chart1 svg').call(chart) });

  chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });

  return chart;
});

var dataForChart=function(){

       var section1 = new Array();
       section1.key="Section 1";
       section1.values = new Array();
       section1.color="#1F77B4";

       var section2 = new Array();
       section2.key="Section2";
       section2.values = new Array();
       section2.color="#2CA02C";

        for (i=0;i<12;i++){
            date=new Date(2013,i,1);

            section1.values[i] = {"y" : Math.round(2*i*getRandom(1,2)), "x": date};
            section2.values[i] = {"y" : Math.round(6*i+2*getRandom(1,2)), "x": date};
         }

         function getRandom(min, max) 
         {
            return Math.random() * (max - min + 1) + min;
         }

         var dataArray=new Array();
         dataArray.push(section1);
         dataArray.push(section2);

       return dataArray;
};    

</script>

if I do not comment out the

如果我不注释掉

//x: function(d,i) { return i},

section, the axis shows Jan70 everywhere.

部分,轴处处显示 Jan70。

For MultiBarChart Code below: MultiBar Result

对于下面的 MultiBarChart 代码:MultiBar 结果

<script>
var chart;
nv.addGraph(function() {
    chart = nv.models.multiBarChart()
      .margin({bottom: 30, top:25})
      .transitionDuration(300)
      .delay(0)
      .groupSpacing(0.2)
      .reduceXTicks(false)
      .showControls(true)
      .showLegend(true)
      .staggerLabels(false)

      ;
    chart.xAxis.tickSize(12)            
             .tickFormat(function(d) {
         console.log(d,arguments);
         var date = new Date(d);
               return d3.time.format('%b %y')(date);
             });

    chart.yAxis
       .axisLabel(dataForChart.ylabel)
       .tickFormat(d3.format(''))
       .axisLabelDistance(50);

    d3.select('#chart1 svg')
        .datum(dataForChart)
       .call(chart);

    nv.utils.windowResize(chart.update);


    chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });

    return chart;
});


var dataForChart=function(){

       var section1 = new Array();
       section1.key="Section 1";
       section1.values = new Array();
       section1.color="#1F77B4";

       var section2 = new Array();
       section2.key="Section2";
       section2.values = new Array();
       section2.color="#2CA02C";

        for (i=0;i<12;i++){
            date=new Date(2013,i,1);

            section1.values[i] = {"y" : Math.round(2*i*getRandom(1,2)), "x": date};
            section2.values[i] = {"y" : Math.round(6*i+2*getRandom(1,2)), "x": date};
         }

         function getRandom(min, max) 
         {
            return Math.random() * (max - min + 1) + min;
         }

         var dataArray=new Array();
         dataArray.push(section1);
         dataArray.push(section2);

       return dataArray;
};    

</script>

回答by AmeliaBR

Line chart axes, like all linear axes, use tick marks to show key points on the line, but not every conceivable value. In many cases, if the chart showed every data, the ticks would be so close together that the labels would overlap and become unreadable. People are expected to be able to estimate the position on the line based on the distance to adjacent tick marks.

折线图轴与所有线性轴一样,使用刻度线来显示线上的关键点,但不是每个可能的值。在许多情况下,如果图表显示所有数据,刻度会靠得很近,以至于标签会重叠并变得不可读。人们期望能够根据到相邻刻度线的距离来估计线上的位置。

In contrast, the x-values for the bar chart are assumed to be distinct categories, which might not have a natural order. They could be "apples", "oranges", and "bananas". There's no way to estimate a middle value ("oranges") based on the values of adjacent labels ("apples" and "bananas"), so by default all the labels are shown, even if they end up overlapping and unreadable.

相反,条形图的 x 值被假定为不同的类别,可能没有自然顺序。它们可以是“苹果”、“橙子”和“香蕉”。无法根据相邻标签(“apples”和“bananas”)的值来估计中间值(“oranges”),因此默认情况下会显示所有标签,即使它们最终重叠且不可读。

But what about your line chart, where you only have 12 date values, so you have room to fit all the labels without overlap? The regular d3 method to tell the axis how many ticks it should include is axis.ticks(). I see you tried to do something similar, but the axis.tickSize()method controls the lengthof each tick line, not how many there are. However, axis.ticks()doesn't work with NVD3 -- the internal methods over-write any value you set on the axis.

但是您的折线图呢,其中只有 12 个日期值,所以您有空间容纳所有标签而不重叠?告诉轴它应该包含多少刻度的常规 d3 方法是axis.ticks(). 我看到你试图做类似的事情,但该axis.tickSize()方法控制每个刻度线的长度,而不是有多少。但是,axis.ticks()不适用于 NVD3——内部方法会覆盖您在轴上设置的任何值。

Don't worry, there is still a way to control it, but it requires some extra code. The axis.tickValues()method supercedes axis.ticks(), so you can use it to over-ride the NVD3 default.

别着急,还是有办法控制的,只是需要一些额外的代码。该axis.tickValues()方法取代了axis.ticks(),因此您可以使用它来覆盖 NVD3 默认值。

The information you include in axis.tickValues()is an arrayof explicit values for each tick. Since your x-axis values are dates, and you have one value for each month, you have two ways of creating this array:

您包含的信息axis.tickValues()是每个刻度的显式值数组。由于您的 x 轴值是日期,并且每个月都有一个值,因此您有两种创建此数组的方法:

Option 1:Get the x values directly from your data.

选项 1:直接从您的数据中获取 x 值。

chart.xAxis.tickValues(ideas.values.map( function(d){return d.x;} ) );

//Array.map(function) creates a new array, where each value is the result of
//calling the function on the corresponding element of the original array.
//Since your data is in ideas.values as an array of {x:date, y:number} objects,
//this method creates an array containing all the dates from your data.

Option 2:Use a d3 time intervalmethod to calculate a sequence of dates.

选项 2:使用 d3时间间隔方法计算日期序列。

chart.xAxis.tickValues(d3.time.month.range(
                            new Date("2013 01"),
                            new Date("2014 01"),
                            1)
                        );

//d3.time.month.range(startDate, stopDate, step) creates the sequence of dates
//that are exact month values, starting with the month on or after the startDate 
//and continuing to the last start of month *before* the stop date
//(so it won't include January 2014.  The step value tell it how many months
//to skip at a time; we want every month, so step==1.

//There are similar methods for year, week, day, hour, minute and second, 
//and also versions for weeks starting on specific days of the week;
//Just replace "month" in "d3.time.month.range" with the appropriate interval.
//For plain numbers, use d3.range(start, stop, step).

I hope that all makes sense now.

我希望现在一切都有意义了。