如何设置域并在nvd3.js multiBarChart上的轴上缩放 [英] how to set the domain and scale on an axis on a nvd3.js multiBarChart

查看:85
本文介绍了如何设置域并在nvd3.js multiBarChart上的轴上缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在d3.js中,您可以将x轴设置为使用d3.time.scale(),然后设置x.domain([start_date, end_date]),它将填充"数据中未包含0值的所有缺失日期.我想对nvd3.js mulitBarChart做同样的事情.

In d3.js you can set an x axis to use d3.time.scale() then set x.domain([start_date, end_date]) and it will 'fill in' any missing dates that aren't in the data with 0 values. I want to do the same with a nvd3.js mulitBarChart.

此代码(可以直接粘贴到 http://nvd3.org/livecode/#codemirrorNav 中)显示一个栏按年度总计的图表,缺少2002年和2002年的值. 2003.我想将小数位数设置为d3.time.scale(),然后将域设置为数据集的第一年和最后一年,因此缺失的年份将自动添加0值.我该怎么办?

This code (can be pasted directly into http://nvd3.org/livecode/#codemirrorNav) shows a bar chart of totals by year, there are missing values for 2002 & 2003. I want to set the scale to be d3.time.scale() and then the domain to the first and last years of the dataset so the missing years are automatically added with 0 values. How do I do that?

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

推荐答案

实际上不需要插值.实际上,您可以修改大多数nvd3图表的比例,包括multiBarCharts,尽管还需要做一些额外的工作才能使它工作.

There is really no need to interpolate your values. You actually can modify the scale of most nvd3 charts, including multiBarCharts, although there is some extra work that needs to be done to make it work.

您需要做的基本事情是:

The basic thing you need to do is this:

var xScale = d3.time.scale();
chart.multibar.xScale(xScale);

那应该就可以了!除非不是,否则因为multiBarChart假定xScale为d3.scale.ordinal().因此,您需要通过设置xScale.rangeBandsxScale.rangeBand来伪造该类型:

Then that should just work! Except it doesn't, because the multiBarChart assumes that the xScale is d3.scale.ordinal(). So you will need to fake being that type by setting xScale.rangeBands and xScale.rangeBand:

xScale.rangeBands = xScale.range;
xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * SOME_VALUE };

现在的问题是得到SOME_VALUE.这需要等于单个条形图的宽度,这取决于两件事:整个图表的宽度和可能存在的刻度线数量,包括数据中缺少的零值.

The problem now is getting SOME_VALUE. This needs to equal the width of an individual bar, which depends on two things: the width of the whole chart and the number of ticks there would be, including the zero values that are missing in the data.

这是nvd3在内部获取可用宽度的方式:

Here's how nvd3 gets the available width internally:

var container = d3.select('#chart svg'),
    availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;

但是,如果调整窗口大小,则需要刷新此值:

However, if the window resizes, you will need to refresh this value:

nv.utils.windowResize(function() {
    availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
});

关于获得报价的数量,这完全取决于您的数据.在您的情况下,将有11个滴答声:在2001年至2011年之间,每年.因此,我们将继续讲下去.因此,整个比例尺定义如下:

As for getting the number of ticks, this depends solely on your data. In your case, there will be 11 ticks: every year between 2001 and 2011. So we'll go with that. Therefore, the entire scale definition looks like this:

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.如果您使用以前的顺序刻度来执行此操作,则它将失败,但是如果使用线性时间刻度,它将可以很好地工作:

Finally, you need to set your xDomain manually. If you did this with the ordinal scale it had before, it would fail, but with a linear time scale it will work excellently:

chart.xDomain([new Date().setFullYear('2001'), new Date().setFullYear('2011')]);

将所有内容放在一起,下面是您的示例代码(可粘贴到 http://nvd3.org/livecode/#codemirrorNav ):

Putting it all together, here is your example code (pasteable into 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;
});

这篇关于如何设置域并在nvd3.js multiBarChart上的轴上缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆