我正在使用d3库绘制一个条形图,其中JSON对象通过websockets从服务器收到。然而,正在发生的是,每次绘制图形时,它都会绘制一个新的图形实例。所以我最终得到了多个图表。
但我希望JSON数据全部绘制在同一个图表上。
这是我的代码:
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);
}
useData.length = 0;
}
}
如何在图表上绘制所有不断更新的点?
令人遗憾的是,d3无法实时处理数据并相应地更新图表,或者如果可以的话,没有明确的教程/解释如何。
由于
答案 0 :(得分:0)
我的猜测是因为你每次创建一个图表:
var chart = d3.select("body")
.append("svg:svg")
.attr("class", "chart")
.attr("width", 420)
.attr("height", 20 * useData.length);
而是需要检查图表是否存在,如果存在,请不要调用该行。
// outside of .onmessage
var chart;
// inside of .onmessage
if (!chart) {
chart = d3.select("body")
.append("svg:svg")
.attr("class", "chart")
.attr("width", 420)
.attr("height", 20 * useData.length);
}
答案 1 :(得分:0)
就像Brian说你在每个onmessage事件中不断创建一个新的svg
元素。但是,在D3中,您不需要使用if
语句来检查元素是否存在;在进行数据连接后,enter()
选择将仅包含尚不存在的元素:
// data join
var chart = d3.select("body").selectAll(".chart")
.data([useData]); // if you wanted multiple charts: .data([useData1, useDate2, useData3])
// enter
chart.enter().append("svg") // this will only execute if the .chart did not exist yet
.attr("class", "chart")
.attr("width", 420);
// update (both new and existing charts)
chart
.attr("height", function(d) { return 20 * d.length; });
Thing with Joins文章介绍了数据连接,enter(),update()和exit()选择的概念。另请参阅3篇General Update Pattern文章。
在图表中更新或添加新的rect元素时,必须使用类似的方法。假设目前useData包含所有累积的数据(虽然useData.length = 0可能意味着不是这种情况):
// data join
var rects = chart.selectAll("rect")
.data(function(d) { return d; }); // use the data bound to each chart
// enter
rects.enter().append("rect");
// update
rects
.attr("y", function(d) { return y(d.yValue); }) // not sure what your data structure looks like
.attr("width", function(d) { return x(d.xValue); })
.attr("height", y.rangeBand());
// exit
rects.exit().remove();
有关如何使用实时数据更新路径的一些建议,请参见Path Transitions。