我正在研究使用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 data和this tutorial)来实现这一点,但这对我来说并不理想,因为最新的某些元素可能会更新,而不是最新的元件。
所以我要做的就是抓住说最近一分钟(通过设置查询字符串(.qs
)只获取最近一分钟,然后取出结果并执行以下操作:< / p>
有人能建议一种优雅的方式来执行上述合并操作吗?现有的数据对象如下所示:
> 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可以做到吗?
答案 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)
});