确实没有必要插入您的值。您实际上可以修改大多数 nvd3 图表的比例,包括 multiBarCharts,尽管需要做一些额外的工作才能使其正常工作。
您需要做的基本事情是:
var xScale = d3.time.scale();
chart.multibar.xScale(xScale);
那应该就行了!除非它没有,因为 multiBarChart 假定 xScale 是d3.scale.ordinal()
. 因此,您需要通过设置xScale.rangeBands
and来伪装自己是那种类型xScale.rangeBand
:
xScale.rangeBands = xScale.range;
xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * SOME_VALUE };
现在的问题是获取 SOME_VALUE。这需要等于单个条的宽度,这取决于两件事:整个图表的宽度和可能存在的刻度数,包括数据中缺少的零值。
以下是 nvd3 如何在内部获取可用宽度:
var container = d3.select('#chart svg'),
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
但是,如果窗口调整大小,您将需要刷新此值:
nv.utils.windowResize(function() {
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
});
至于获取滴答数,这完全取决于您的数据。在您的情况下,将有 11 个刻度:从 2001 年到 2011 年每年。所以我们将继续这样做。因此,整个比例定义如下所示:
var container = d3.select('#chart svg'),
availableWidth,
numTicks = 11,
xScale = d3.time.scale();
function updateAvailableWidth() {
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
}
updateAvailableWidth();
nv.utils.windowResize(updateAvailableWidth);
xScale.rangeBands = xScale.range;
xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * availableWidth / numTicks; };
chart.multibar.xScale(xScale);
最后,您需要手动设置 xDomain。如果你用它以前的序数尺度来做这个,它会失败,但是使用线性时间尺度它会很好地工作:
chart.xDomain([new Date().setFullYear('2001'), new Date().setFullYear('2011')]);
综上所述,这是您的示例代码(可粘贴到http://nvd3.org/livecode/#codemirrorNav中):
nv.addGraph(function() {
var chart = nv.models.multiBarChart(),
container = d3.select('#chart svg'),
availableWidth,
numTicks = 11,
xScale = d3.time.scale();
function updateAvailableWidth() {
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
}
updateAvailableWidth();
nv.utils.windowResize(updateAvailableWidth);
xScale.rangeBands = xScale.range;
xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * availableWidth / numTicks; };
chart.multibar.xScale(xScale);
chart.xDomain([new Date().setFullYear('2001'), new Date().setFullYear('2011')]);
chart.xAxis
.tickFormat(function(d){ return d3.time.format('%y')(new Date(d)); });
chart.yAxis
.tickFormat(d3.format(',f'));
chart.reduceXTicks(false);
chart.showControls(false);
var data = [{
'key': 'GB by year',
'values': [
{x: new Date().setFullYear('2001'), y: 0.12},
{x: new Date().setFullYear('2004'), y: 0.03},
{x: new Date().setFullYear('2005'), y: 0.53},
{x: new Date().setFullYear('2006'), y: 0.43},
{x: new Date().setFullYear('2007'), y: 5.5},
{x: new Date().setFullYear('2008'), y: 9.9},
{x: new Date().setFullYear('2009'), y: 26.85},
{x: new Date().setFullYear('2010'), y: 0.03},
{x: new Date().setFullYear('2011'), y: 0.12}
]
}];
container.datum(data).transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});