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

Javascript d3.js nvd3 x轴上的日期:仅显示一些日期,javascript,date,d3.js,nvd3.js,Javascript,Date,D3.js,Nvd3.js,我对在X轴上显示日期有一个奇怪的问题。 我生成的数据如下所示: 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}; } chart.xAxis.tickSize(12) .tickFormat(function(d) {

我对在X轴上显示日期有一个奇怪的问题。 我生成的数据如下所示:

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};
}
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个)

现在更奇怪的事情是:将完全相同的数据放在多条形图中,并使用完全相同的图表。xAxis。。。。函数,测试数组内容为12个值

我说不出话来,希望有人能帮我

谢谢你们

完整代码如下:

对于折线图:

在剖面图中,轴上到处都是Jan70

对于下面的多重条形图代码:


var图;
nv.addGraph(函数(){
chart=nv.models.multiBarChart()
.margin({底部:30,顶部:25})
.过渡期(300)
.延迟(0)
.组间距(0.2)
.reduceXTicks(假)
.showControls(真)
.showLegend(真实)
.错误标签(错误)
;
图表.xAxis.tickSize(12)
.d格式(函数(d){
log(d,参数);
var日期=新日期(d);
返回d3.time.format(“%b%y”)(日期);
});
图1.yAxis
.axisLabel(dataForChart.ylabel)
.tickFormat(d3.format(“”))
.轴间距(50);
d3.选择(“#图表1 svg”)
.基准面(dataForChart)
.电话(图表);
nv.utils.windowResize(图表更新);
on('stateChange',function(e){nv.log('newstate:',JSON.stringify(e));});
收益表;
});
var dataForChart=函数(){
var section1=新数组();
section1.key=“Section 1”;
section1.values=新数组();
第1节颜色=“#1F77B4”;
var section2=新数组();
section2.key=“section2”;
section2.values=新数组();
第2节颜色=“#2CA02C”;

对于(i=0;i与所有线性轴一样,折线图轴使用刻度线来显示线上的关键点,但不是所有可能的值。在许多情况下,如果图表显示所有数据,刻度线会靠得太近,以至于标签会重叠且无法读取。人们希望能够根据d估计线上的位置与相邻记号的距离

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

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

别担心,仍然有一种方法可以控制它,但它需要一些额外的代码。该方法取代了
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方法计算日期序列

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

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

除非您向我们展示您如何创建和使用此数组的完整代码,否则我们无法真正帮助您。感谢您的回复。我现在粘贴了整个代码。我仍然不完全确定您的问题。是否与@AmeliaBR的回复假设的滴答声有关?我在发布此消息后看到了您的更新;基于更多信息复杂的代码(有两个数据系列),您必须从中选择一个数据系列(哪一个数据系列并不重要,因为两个数据系列的日期相同),从中获取值数组,并将其用于map函数。“Option 2”方法不会更改,因此使用它可能更简单、更一致。tickValues(…)对我来说效果很好。但我仍然不明白为什么它在柱状图上没有任何问题。它是一种不同类型的刻度——一种类别(“序数”)刻度,恰好以日期或数字作为类别名称,而不是连续(“线性”)刻度。因此有不同的默认行为。v3的更新链接:
<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>
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.
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).