【问题标题】:d3.js nvd3 date on x axis: only some dates are showx 轴上的 d3.js nvd3 日期:仅显示一些日期
【发布时间】:2014-02-14 11:59:15
【问题描述】:

我在 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};
}

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

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

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

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

我无语了,希望有人能帮帮我。

谢谢你们!

完整代码如下:

对于折线图:lineChart Result

<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>

如果我不注释掉

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

部分,坐标轴处处显示 Jan70。

对于下面的 MultiBarChart 代码:MultiBar Result

<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>

【问题讨论】:

  • 除非您向我们展示您如何创建和使用此数组的完整代码,否则我们无法真正帮助您。
  • 感谢您的回复。我现在粘贴了整个代码。
  • 我仍然不完全确定你在问什么。是关于@AmeliaBR 的回复假设的蜱虫吗?

标签: javascript date d3.js nvd3.js


【解决方案1】:

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

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

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

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

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

选项 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.

选项 2:使用 d3 time interval 方法计算日期序列。

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).

我希望现在一切都说得通了。

【讨论】:

  • 我在发布此消息后看到了您的更新;基于更复杂的代码(有两个数据系列),你必须选择一个数据系列(不管哪个,因为两者都有相同的日期),从中获取值数组,并使用它对于地图功能。 “选项 2”方法没有改变,因此使用起来可能更容易、更一致。
  • .tickValues(...) 对我来说效果很好。但我仍然不明白为什么它在之前没有任何问题的情况下适用于 BarChart..
  • 它是一种不同类型的比例尺——一种类别(“序数”)比例尺,恰好有日期或数字作为类别名称,而不是连续(“线性”)比例尺。所以有不同的默认行为。
猜你喜欢
  • 2012-12-13
  • 1970-01-01
  • 2017-12-24
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
相关资源
最近更新 更多