通过合并更新D3.js(NVD3.js)数据

时间:2013-07-16 13:45:21

标签: javascript d3.js nvd3.js

我正在研究使用NVD3.js构建的一些实时图表。我目前用以下内容刷新每个图表:

function reDraw(c) {
    d3.json(c.qs, function(data) {
        d3.select(c.svg)
        .datum(data)
        .transition().duration(500)
        .call(c.chart);
    });
}

c看起来像:

function Chart(svg, qs, chart) {
    this.qs = qs;
    this.svg = svg;
    this.ylabel;
    this.chart;
}

这很好用,但每次刷新我都会再次获取整个时间序列。仅抓取最近的元素并更新每个图表会更有效。有一些例子可以通过附加元素(例如,这个答案NVD3 line chart with realtime datathis tutorial)来实现这一点,但这对我来说并不理想,因为最新的某些元素可能会更新,而不是最新的元件。

所以我要做的就是抓住说最近一分钟(通过设置查询字符串(.qs)只获取最近一分钟,然后取出结果并执行以下操作:< / p>

  • 使用最新数据覆盖具有相同x值的任何现有元素
  • 在每个系列的更新中有新的x值时附加和元素
  • 超过某个年龄的元素
  • 使用新数据更新NVD3.js脚本。也许仍然使用新合并对象的数据?

有人能建议一种优雅的方式来执行上述合并操作吗?现有的数据对象如下所示:

> d3.select(perf.svg).data()[0]
[
Object
key: "TrAvg"
values: Array[181]
__proto__: Object
, 
Object
key: "RedisDurationMsAvg"
values: Array[181]
__proto__: Object
, 
Object
key: "SqlDurationMsAvg"
values: Array[181]
__proto__: Object
]
> d3.select(perf.svg).data()[0][0]['values'][0]
Object {x: 1373979220000, y: 22, series: 0}
> d3.select(perf.svg).data()[0][1]['values'][0]
Object {x: 1373979650000, y: 2, series: 1}

返回的对象看起来如下所示(除了每个对象只有6个元素左右):

> d3.json(perf.qs, function(data) { foo = data })
Object {header: function, mimeType: function, response: function, get: function, post: function…}
> foo
[
Object
, 
Object
, 
Object
]
> foo[0]
Object {key: "TrAvg", values: Array[181]}
> foo[0]['values'][0]
Object {x: 1373980220000, y: 49}

在这个较新的对象中,系列值缺失 - 可能需要添加或者D3可以做到吗?

1 个答案:

答案 0 :(得分:-1)

目前我使用linq.js来执行此操作,然后每次使用.datum()绑定新数据集。解决方案不是很优雅,但似乎确实有效:

function reDraw2(c, partial) {
    if (partial) {
        qs = c.qs.replace(/minago=[0-9]+/, "minago=1")
    } else {
        qs = c.qs
    }
    d3.json(qs, function(new_data) {
        chart = d3.select(c.svg)
        if (c.ctype == "ts" && partial) {
            thirtyminago = new Date().getTime() - (60*30*1000);
            old_data = chart.data()[0]
            var union = new Array();
            for (var i = 0; i < old_data.length; i++) {
                var existing = Enumerable.From(old_data[i]['values']);
                var update = Enumerable.From(new_data[i]['values']);
                oldfoo = existing
                newfoo = update
                var temp = {}
                temp['key'] = old_data[i]['key']
                temp['values'] = update.Union(existing, "$.x").Where("$.x >" + thirtyminago).OrderBy("$.x").Select().ToArray();
                union[i] = temp

            }
            chart.datum(union)
        } else {
            chart.datum(new_data)
        }
        chart.call(c.chart)
    });