正如@Miichi 所说,这是nvd3 中的一个错误...
令我惊讶的是,他们有一个 TODO 来“找出为什么值似乎发生了变化”,因为这很明显......条形使用带有 .rangeBands() 的序数刻度,而线条使用线性刻度,并且这两个尺度从来没有相互关联,除非它们共享相同的端点。
一种解决方案是从条形图中获取序数比例,然后简单地将其调整为条形宽度的一半以形成线条的 x 比例。这会将线点放在条形的中心。我想在@LarsKotthoff 提到的nv.models.linePlusBarChart 中也做了类似的事情。
基本上,您的生产线的 x 比例如下所示:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
...其中xScaleBars 是用于图表条形部分的 x 比例。
通过梳理 nvd3 的源代码,这个比例似乎可以通过chart.bars1.scale() 访问。
也许有一天 nvd3 的作者会决定,他们的图书馆组合值得一些文档。现在,我可以通过制作一个自定义图表并展示这两个比例如何关联,向您展示可以解决问题的种类。
首先,我将使用您的数据,但将线和条数据分成两个数组:
var barData = [
{"x":0,"y":6500},
{"x":1,"y":8600},
{"x":2,"y":17200},
{"x":3,"y":15597},
{"x":4,"y":8600},
{"x":5,"y":814}
];
var lineData = [
{"x":0,"y":2},
{"x":1,"y":2},
{"x":2,"y":4},
{"x":3,"y":6},
{"x":4,"y":2},
{"x":5,"y":5}
];
然后设置条形的比例。对于 x 比例,我将使用序数比例和 rangeRoundBands,nvd3 的 multiBar 的默认组间距为 0.1。对于 y 比例,我将使用常规线性比例,使用.nice(),这样比例就不会像 nvd3 中的默认值那样以尴尬的值结束。在最大值上方留出一些空间可以为您提供一些上下文,这在尝试解释图表时“很好”。
var xScaleBars = d3.scale.ordinal()
.domain(d3.range(barData.length))
.rangeRoundBands([0, w], 0.1);
var yScaleBars = d3.scale.linear()
.domain([0, d3.max(barData, function(d) {return d.y;})])
.range([h, 0])
.nice(10);
现在这是重要的部分。对于线条的 x 比例,不要单独制作比例,而只需 使其成为条的 x 比例的函数:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
这是JSBin 的完整示例。我已经尝试用 cmets 记录主要部分,因此很容易遵循它的整体逻辑。如果您可以从 nvd3 源代码中准确了解 multiChart 的每个元素被称为什么以及如何设置组成部分的各个比例,那么您也许可以插入新的比例。
我的感觉是,您需要很好地了解 d3 如何使用 nvd3 做任何有用的事情,如果您想自定义它,最好只滚动您自己的图表。这样,您就可以完全了解和控制图表各部分的元素类和变量名称,并且可以对它们做任何您想做的事情。如果 nvd3 得到适当的文档,也许这将成为一个简单的修复。祝你好运,我希望这至少可以帮助你入门。