我正在尝试使用接收到的数据更新图表,以便随着通过 websocket 从服务器接收到更多数据,条形图的高度会增加。但是我的代码不会在浏览器中呈现图形并绘制数据点。我看不出代码有什么问题。我真的需要一些帮助。
ws = new WebSocket("ws://localhost:8888/dh");
var useData = []
//var chart;
var chart = d3.select("body")
.append("svg:svg")
.attr("class", "chart")
.attr("width", 420)
.attr("height", 200);
ws.onmessage = function(evt)
{
var distances = JSON.parse(evt.data);
data = distances.miles;
console.log(data);
if(useData.length <= 10){
useData.push(data)
}
else
{
var draw = function(data){
// Set the width relative to max data value
var x = d3.scale.linear()
.domain([0, d3.max(useData)])
.range([0, 420]);
var y = d3.scale.ordinal()
.domain(useData)
.rangeBands([0, 120]);
var rect = chart.selectAll("rect")
.data(useData)
// enter rect
rect.enter().append("svg:rect")
.attr("y", y)
.attr("width", x)
.attr("height", y.rangeBand());
// update rect
rect
.attr("y", y)
.attr("width", x)
.attr("height", y.rangeBand());
var text = chart.selectAll("text")
.data(useData)
// enter text
text.enter().append("svg:text")
.attr("x", x)
.attr("y", function (d) { return y(d) + y.rangeBand() / 2; })
.attr("dx", -3) // padding-right
.attr("dy", ".35em") // vertical-align: middle
.attr("text-anchor", "end") // text-align: right
.text(String);
// update text
text
.data(useData)
.attr("x", x)
.text(String);
}
draw();
useData.length = 0;
}
}
谢谢
编辑:
但是现在的问题是,它似乎并没有将新数据添加到现有柱中,而是替换了旧值。我怎样才能将新值添加到现有的条值中。因此,例如,如果条形图“A”的值为 7,当新数据来自条形图“A”的值为 9 时,条形图现在应该为 16 而不是 9。jsfiddle:http://jsfiddle.net/2NXF2/31/
最佳答案
似乎没有将新数据与上一次迭代的旧数据聚合的表达式。 useData.length = 0
完全清除现有数据,useData.push(data)
仅将单个元素推送到空的 useData
数组.我猜这不会产生要绘制的必要格式的数据。
此外,我可能在这里遗漏了一些东西,但似乎没有理由将 draw()
函数放在 ws.onmessage
处理程序中。通过在处理程序外部定义 draw()
,它被定义一次而不是每次 ws.onmessage
触发时都重新定义。
如果我是对的,那么代码只需要重新安排一下,在大大减少的 ws.onmessage
处理程序中加上一个小循环,以将新里程与旧里程聚合:
var ws = new WebSocket("ws://localhost:8888/dh");
var useData = [12,45,48,45,654,12,465,5,12,45];
var chart = d3.select("body").append("svg:svg").attr("class", "chart").attr("width", 420).attr("height", 200);
function draw() {
// Set the width relative to max data value
var x = d3.scale.linear().domain([0, d3.max(useData)]).range([0, 420]);
var y = d3.scale.ordinal().domain(useData).rangeBands([0, 120]);
var rect = chart.selectAll("rect").data(useData);
// enter rect
rect.enter().append("svg:rect").attr("y", y).attr("width", x).attr("height", y.rangeBand());
// update rect
rect.attr("y", y).attr("width", x).attr("height", y.rangeBand());
var text = chart.selectAll("text").data(useData);
// enter text
text.enter().append("svg:text").attr("x", x).attr("y", function(d) {
return y(d) + y.rangeBand() / 2;
}).attr("dx", -3) // padding-right
.attr("dy", ".35em") // vertical-align: middle
.attr("text-anchor", "end") // text-align: right
.text(String);
// update text
text.data(useData).attr("x", x).text(String);
};
draw();//initialise with hard-coded useData
//Now, aggregate additional miles when ws.onmessage fires and redraw the graph.
ws.onmessage = function(evt) {
var distances = JSON.parse(evt.data);
for(var i=0; i<useData.length; i++) {
if(useData[i] && distances.miles[i]) {//safety
useData[i] += distances.miles[i];//add the new miles to the total from previous iteration
}
}
draw();//redraw the graph
}
注意事项:
- 我不熟悉 d3,所以我没有尝试验证 draw()
函数。
- 我做了很多猜测,所以可能还有一些工作要做。
关于javascript - 从服务器实时更新图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13782830/