在d3.js中,您可以设置x轴使用d3.time.scale()然后设置x.domain([start_date, end_date]),它将"填写"任何缺少的日期,这些日期不在数据中,值为0.我想用nvd3.js做同样的事情mulitBarChart.
此代码(可直接粘贴到http://nvd3.org/livecode/#codemirrorNav)显示按年份计算的总计条形图,2002和2003中缺少值.我想将比例设置为d3.time.scale()然后域到数据集的第一年和最后几年,因此缺失的年份会自动添加0值.我怎么做?
nv.addGraph(function() {
var chart = nv.models.multiBarChart();
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}
]
}];
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
Run Code Online (Sandbox Code Playgroud)
tma*_*hal 12
基于上面的答案,您可以使用数字x值(不是Date对象)以及强制X范围和指定的tickValues ....来处理某些类型的图表.
条形图似乎没有这种能力,但是nvd3.lineCharts可以做你想做的事.multiBarChart模型不允许使用forceX函数(现在,永远?).
您的问题的解决方案是填写0或使用顺序图表类型(例如lineChart)
nv.addGraph(function() {
var chart = nv.models.lineChart()
.forceX(2001,2011);
var tickMarks = [2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011]
chart.xAxis
.tickValues(tickMarks)
.tickFormat(function(d){ return d });
chart.yAxis
.tickFormat(d3.format(',f'));
var data = [{
'key': 'GB by year',
'values': [
{x: 2001, y: 0.12},
{x: 2004, y: 0.03},
{x: 2005, y: 0.53},
{x: 2006, y: 0.43},
{x: 2007, y: 5.5},
{x: 2008, y: 9.9},
{x: 2009, y: 26.85},
{x: 2010, y: 0.03},
{x: 2011, y: 0.12}
]
}];
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart1.update);
return chart;
});
Run Code Online (Sandbox Code Playgroud)
您可以通过两种方式执行此操作:
A)你要么重写nvd3的轴组件,要使用d3.time.scale()/ make这个用例的另一个轴组件......
或者最简单的方法:
B)您使用轴的自定义值.首先,使用+运算符(+(date))来获取以ms为单位的值.在d3中有一个tickValues函数,允许你为ticks传递自定义值.为了强制X缩放,你有分散的forceX()方法(我假设你已经知道了这一点),你写了一个简单的函数,获取刻度的自定义值....因此,如果您强制您的刻度值在2002年1月1日到2012年12月31日之间,然后决定有4个刻度,您可以直接使用刻度线或tickValues ...
所以它是这样的(添加类似于multiBarChart.js文件):
lines.forceX(minValue, maxValue) //where minValue and maxValue are the values
//converted to ms already after you did +(date)
//then you just rewrite the ticks - if you want a custom number of ticks you can do it like this
//numberOfTicks is a method I added to the axis component (axis.js) to give the number of ticks the user would like to have
//x.domain() now contains the forced values instead of the values you initially used..
var maxTicks = xAxis.numberOfTicks()-1, xMin = x.domain()[0], xMax = x.domain()[1],
xDiff = (xMax - xMin)/maxTicks, tickInterval = [];
tickInterval[0] = xMin;
for(i=1; i<maxTicks; i++){
var current = xMin + i*xDiff;
tickInterval[i] = current;
}
tickInterval[maxTicks] = xMax;
//tickInterval already contains the values you want to pass to the tickValues function
xAxis.tickValues(tickInterval);
Run Code Online (Sandbox Code Playgroud)
希望这有帮助...我知道它是黑客但它在我的情况下工作:)当然,如果你已经格式化日期显示为年份,你将获得显示滴答的年份的值:)
这就是我为线条做的.对于multiBarChart,您需要添加一个额外的步骤:您需要处理reduceTicks功能(将其设置为false,删除该部分代码,随意执行任何操作......)
实际上没有必要插值.您实际上可以修改大多数nvd3图表的比例,包括multiBarCharts,尽管还需要做一些额外的工作才能使其工作.
你需要做的基本事情是:
var xScale = d3.time.scale();
chart.multibar.xScale(xScale);
Run Code Online (Sandbox Code Playgroud)
然后那应该工作!除非它没有,因为multiBarChart假定xScale是d3.scale.ordinal().所以你需要通过设置xScale.rangeBands和伪造这种类型xScale.rangeBand:
xScale.rangeBands = xScale.range;
xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * SOME_VALUE };
Run Code Online (Sandbox Code Playgroud)
现在的问题是获得SOME_VALUE.这需要等于单个条的宽度,这取决于两个方面:整个图表的宽度和将要有的刻度数,包括数据中缺少的零值.
以下是nvd3如何在内部获得可用宽度:
var container = d3.select('#chart svg'),
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
Run Code Online (Sandbox Code Playgroud)
但是,如果窗口调整大小,则需要刷新此值:
nv.utils.windowResize(function() {
availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
});
Run Code Online (Sandbox Code Playgroud)
至于获取滴答数,这完全取决于您的数据.在你的情况下,将有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);
Run Code Online (Sandbox Code Playgroud)
最后,您需要手动设置xDomain.如果你用它之前的序数量表做到这一点,它就会失败,但是如果有一个线性的时间尺度,它将会很好地工作:
chart.xDomain([new Date().setFullYear('2001'), new Date().setFullYear('2011')]);
Run Code Online (Sandbox Code Playgroud)
总而言之,这是您的示例代码(可粘贴到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;
});
Run Code Online (Sandbox Code Playgroud)