NVD3.js multiChart x轴标签与多条线对齐,但不是多条线

时间:2014-07-17 07:41:17

标签: d3.js nvd3.js

此问题与NVD3.js multiChart x-axis labels is aligned to lines, but not bars

有关

我正在使用NVD3.js multiChart在图表中显示多行多个栏。一切正常,但x轴标签仅与线点对齐,而不是条线。我想正确地将标签正确地对齐标签。但我明白了:

x-axis labels is not aligned to bars

如您所见 - x轴(例如,2014年 - 2月)未与条形对齐。

1)如何将x轴标签同时与条形和线条对齐

2)我需要NVD3.js的此解决方案或如何正确集成。

我制作了jsFiddle:http://jsfiddle.net/n2hfN/28/

谢谢!

6 个答案:

答案 0 :(得分:10)

这里的问题是nv.models.multiChart使用线性比例作为其x轴,然后当它绘制条形时它调用nv.models.multiBar,它使用带有.rangeBands()的序数比例。

你可以通过源代码跟踪这个混乱:

首先让我们看一下multiChart.js

HERE是将x刻度设置为线性刻度的地方。

HERE它调用nv.models.multiBar模型来创建条形图。

如果我们跳过去查看multiBar.js

HERE它会创建一个序数比例,HERE它会使用.rangeBands()设置比例范围

结果是用于放置条形的序数比例和用于图表轴的线性比例不对齐。如果在轴上绘制,这就是两个尺度自己的样子:

d3 ordinal vs linear scale

解决方案是强制图表根据条形使用的序数比例渲染折线图和x轴。这将适用于您的情况,因为条形和线条都使用相同的x轴数据。如果您制作自己的图表并且不依赖于nvd3,这很简单,正如我在回答您之前的问题HERE时所示。如果您尝试在nvd3中工作,这是非常复杂的,许多其他人已经尝试并且未能切换出nvd3图表使用的默认比例。请查看自2013年1月以来一直开放的this issue on the nvd3 github page

我自己尝试了很多方法来重复使用条形序列,但收效甚微。如果你想四处寻找并尝试自己暴力破解,我可以告诉你,在我的实验中,当我使用chart.bars1.xScale().copy()制作条形图的副本时,我最接近,并设置了它的域和范围。不幸的是,由于图表的宽度是在渲染时计算的,而我似乎无法在chart.update函数中创建钩子,因此无法将rangeBands的范围设置为正确的值。

简而言之,如果您不能使用偏移的标签,您可能需要在没有nvd3的情况下编写自己的图表,或者为您的可视化找到不同类型的布局。

答案 1 :(得分:4)

在使用jshanley的答案提供的极其有用的指导来玩NVD3 v1.7.1源代码后,我想我已经设法得到了答案(或许更多的是一个比一个很好的解决方案)。

  1. 我所做的是让x轴标签与条形对齐,并使线条数据点与条形对齐。

    1.1。为了对齐x轴标签,我将x轴向右移动,使第一个标签出现在第一个条的中间。然后我将最后一个标签向左移动,使它出现在最后一个条的中间。请参阅代码here。转换的数量是使用.rangeBand()在绘图时计算的,并保存在rbcOffset变量中(我必须修改multiBar.js才能使其生效)。

    1.2。为了使线数据点与条对齐,还需要类似的移位。幸运的是,这部分很容易,因为scatter.js(由折线图使用)附带一个padData布尔变量,它可以完成我们想要的操作。所以基本上,我只是将padData设置为true并且线条移动以与条形对齐,请参阅here

  2. 为了与NVD3正确集成并使一切看起来都很好,还需要进行一些额外的更改。我在GitHub上分配了NVD3,这样你就可以在那里看到完整的解决方案。当然,欢迎捐款。

答案 2 :(得分:3)

我使用上一个解决方案然后运行。所以,你可以指定

lines1.padData(true)

也是为了对齐线条。

答案 3 :(得分:0)

在这里,我使用了最后一个解决方案,它也适用于我。在multiChart.js中找到以下行

if(dataLines1.length){
    lines1.scatter.padData(true); // add this code to make the line in sync with the bar
    d3.transition(lines1Wrap).call(lines1);
}

答案 4 :(得分:0)

我遇到了同样的问题并使用以下代码修复了它:

在第7832和7878行替换

line.replace(';', ';\n')

with:

.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })

第一种情况处理多个条形外壳,而第二种情况处理单个条形外壳。

答案 5 :(得分:0)

劳瑞的解决方案有效。同样,如果使用交互式指南,则需要移动交互式行以匹配新比例。修改:

if(useInteractiveGuideline){
                interactiveLayer
                    .width(availableWidth)
                    .height(availableHeight)
                    .margin({left:margin.left, top:margin.top})
                    .svgContainer(container)
                    .xScale(x);
                wrap.select(".nv-interactive").call(interactiveLayer);    
                                                                          
                //ADD THIS LINE 
                wrap.select(".nv-interactiveGuideLine")
                .attr('transform', 'translate(' + rbcOffset +', ' + 0  + ')' +
                'scale(' + ((availableWidth - rbcOffset*2)/availableWidth) + ', 1)');
            }

在multiChart.js中。