D3.js 具有实时数据的NVD3折线图

D3.js 具有实时数据的NVD3折线图,d3.js,nvd3.js,D3.js,Nvd3.js,我有一个使用NVD3.js编写的非常简单的折线图。我已经写了一个基于计时器的简单重画,从我看到的示例中提取,但是我得到了错误 未捕获的TypeError:无法读取未定义的属性“y” JS是 var data = [{ "key": "Long", "values": getData() }]; var chart; nv.addGraph(function () { chart = nv.models.cumu

我有一个使用NVD3.js编写的非常简单的折线图。我已经写了一个基于计时器的简单重画,从我看到的示例中提取,但是我得到了错误

未捕获的TypeError:无法读取未定义的属性“y”

JS是

    var data = [{
        "key": "Long",
        "values": getData()
    }];
    var chart;

    nv.addGraph(function () {
          chart = nv.models.cumulativeLineChart()
                      .x(function (d) { return d[0] })
                      .y(function (d) { return d[1] / 100 })
                      .color(d3.scale.category10().range());

        chart.xAxis
            .tickFormat(function (d) {
                return d3.time.format('%x')(new Date(d))
            });

        chart.yAxis
            .tickFormat(d3.format(',.1%'));

        d3.select('#chart svg')
            .datum(data)
            .transition().duration(500)
            .call(chart);

        nv.utils.windowResize(chart.update);

        return chart;
    });


    function redraw() {
        d3.select('#chart svg')
            .datum(data)
          .transition().duration(500)
            .call(chart);
    }

    function getData() {
        var arr = [];
        var theDate = new Date(2012, 01, 01, 0, 0, 0, 0);
        for (var x = 0; x < 30; x++) {
            arr.push([theDate.getTime(), Math.random() * 10]);
            theDate.setDate(theDate.getDate() + 1);
        }
        return arr;
    }

    setInterval(function () {
        var long = data[0].values;
        var next = new Date(long[long.length - 1][0]);
        next.setMonth(next.getMonth() + 1)
        long.shift();
        long.push([next.getTime(), Math.random() * 100]);
        redraw();
    }, 1500);
评论后的第二个答案

我看了看。您可以看到在图表创建过程中创建的display.y属性。它依赖于一个私有方法:indexify。如果该方法的某些衍生工具被公开,那么也许您可以在重画之前执行类似chart.reindexify的操作

作为临时解决办法,您可以在每次更新时从头开始重新创建图表。如果你删除了这个过渡,它似乎可以正常工作。示例JSIDLE:

第一个答案

我相信电子艺界有漏洞。cumulativeLineChart似乎向序列中的数据值动态添加了display.y属性。但是,当向序列中添加新值以进行重画时,它不会重新生成此属性。我不知道如何让它做到这一点,尽管我是NVD3新手

你真的需要一个累积的图表,还是一个普通的折线图就足够了?如果是这样,我必须对您的代码进行以下更改:

从累积图表更改为折线图 从使用二维数据数组更改为使用具有x、y属性的数据对象 我对NVD3不太熟悉,无法说出需要什么样的数据格式。2D数组显然适用于初始加载,但我认为它无法用于后续重画。这可能与您在cumulativeLineChart中遇到的相同问题有关。我原以为更改为对象也可以修复累积的TiveLineChart,但似乎没有。 我还改变了以下内容,尽管没有那么重要:

修改getData函数以创建日期的新实例,以避免在日期增加时共享引用的意外后果

修改了更新间隔函数,以天而不是月为增量生成新数据,y值的范围与getData函数相同

下面是一个处理这些更改的JSFIDLE:


我遇到了同样的问题。我将行上的y函数从

.y(function(d) { return d.display.y })


这样就消除了错误。显然,它不会在错误情况下显示不存在的索引值,但根据我的经验,图表会在定义了显示的情况下再次更新,并且看起来是正确的。

我找到了我认为更好的解决方案。出现此问题是因为累积图表在处理过程中设置了y函数。每当您想要刷新图表时,首先将其设置回返回正确原始y的默认值。在重绘函数中,在更新之前执行以下操作:

chart.y(function (d) { return d.y; });

如果累积图表能够自己做到这一点,那么更好的方法是在设置新的访问函数之前存储原始的访问函数,并在重新索引之前将其放回原处。如果有机会的话,我会尝试进行修复。

你能添加一个JSFIDLE来演示这个问题吗?@JaimalChohan你是如何修复这个问题的?不,它需要是一个累积折线图,我简化了JSFIDLE,只显示了一行,以使问题更容易理解。嗯,我真的认为这是NVD3中的某种缺陷。通过向数据点手动添加display:{y:?}属性,我能够在不引发错误的情况下创建cumulativeLineChart函数。JSFIDLE:。当然,结果是不正确的。我认为唯一的办法是检查源代码,并找出如何在重画时生成/更新该属性。实际上,我更喜欢上面的评论作为解决方案,因为您问题中提出的建议会导致重画整个图表。除了一个容易解决的插值问题,这是我一直在寻找的
chart.y(function (d) { return d.y; });