Javascript 在socket.on(socket io)内绘制d3实时折线图
我正在使用通过socket io从服务器接收的值,我想制作一个图表,在新值到达时实时更新 为了绘制图形,我使用本例中的代码: 我收到以下表格中的数据:Javascript 在socket.on(socket io)内绘制d3实时折线图,javascript,node.js,sockets,d3.js,Javascript,Node.js,Sockets,D3.js,我正在使用通过socket io从服务器接收的值,我想制作一个图表,在新值到达时实时更新 为了绘制图形,我使用本例中的代码: 我收到以下表格中的数据: socket.on('news', function (data) { /*I make the chart here*/...}); 我用自己的值替换了next()函数中的value字段,即从套接字接收的值,所有工作都很好 唯一的问题是,每当一个新的数据点到达时,每两秒钟,不仅图形会得到更新,而且我会在浏览器中得到同一个图表的精确副本,在已
socket.on('news', function (data) { /*I make the chart here*/...});
我用自己的值替换了next()
函数中的value
字段,即从套接字接收的值,所有工作都很好
唯一的问题是,每当一个新的数据点到达时,每两秒钟,不仅图形会得到更新,而且我会在浏览器中得到同一个图表的精确副本,在已经存在的图形下面。每次我收到一个新的数据点时,这种情况都会继续发生,直到最终我的浏览器中有20个或更多图表,导致它在某个点崩溃
我尝试在上的socket.on之外创建图表,甚至像上面的示例一样使用随机数据,但它没有显示任何内容。因此,我假设我需要创建图形,并在socket.on()方法中每两秒钟更新一次。
如何创建和更新图表而不制作多个副本
以下是我现在拥有的完整代码:
socket.on('news', function (data) {
var o= JSON.parse(data);
awesome=o;
note3.push(awesome.valuee);
var t = -1
var n = 40,
duration = 750
data = d3.range(n).map(next);
function next(){
return {time: ++t, value: awesome.valuee }
}
var margin = {
top: 6,
right: 0,
bottom: 20,
left: 40
},
width = 560 - margin.right,
height = 120 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([t-n+1, t])
.range([0, width]);
var y = d3.time.scale()
.range([height, 0])
.domain([0, 400]);;
var line = d3.svg.line()
.interpolate("basis")
.x(function (d, i) {return x(d.time);})
.y(function (d, i) {return y(d.value);});
var svg = d3.select("body").append("p").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis=xAxis); */
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data])
.attr("class", "line");
tick();
function tick() {
// update the domains
x.domain([t - n + 2 , t]);
// push the accumulated count onto the back, and reset the count
data.push(next());
// redraw the line
svg.select(".line")
.attr("d", line)
.attr("transform", null);
// slide the x-axis left
axis.transition()
.duration(duration)
.ease("linear")
.call(x.axis);
// slide the line left
path.transition()
.duration(duration)
.ease("linear")
.attr("transform", "translate(" + x(t-n) + ")")
.each("end", tick);
// pop the old data point off the front
data.shift();
}
});
非常感谢。完全未经测试的代码,但您需要重新构造为以下内容:
var t = -1,
n = 40,
duration = 750,
data = [];
var margin = {
top: 6,
right: 0,
bottom: 20,
left: 40
},
width = 560 - margin.right,
height = 120 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([t - n + 1, t])
.range([0, width]);
var y = d3.time.scale()
.range([height, 0])
.domain([0, 400]);;
var line = d3.svg.line()
.interpolate("basis")
.x(function(d, i) {
return x(d.time);
})
.y(function(d, i) {
return y(d.value);
});
var svg = d3.select("body").append("p").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis = xAxis); * /
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data])
.attr("class", "line");
function tick() {
// update the domains
x.domain([t - n + 2, t]);
// redraw the line
svg.select(".line")
.attr("d", line)
.attr("transform", null);
// slide the x-axis left
axis.transition()
.duration(duration)
.ease("linear")
.call(x.axis);
// slide the line left
path.transition()
.duration(duration)
.ease("linear")
.attr("transform", "translate(" + x(t - n) + ")");
// pop the old data point off the front
if (data.length > 40) data.shift();
}
socket.on('news', function(p) {
p = JSON.parse(p);
data.push({
time: ++t,
value: p.valuee
})
tick();
});
我已经使用ws-websocket实现了D3的实时绘图,您可以查看它,这是脚本,您在这里也会有html,但没有添加,此外,还有一个服务器,它为D3文件提供服务并生成随机json,您可以创建此服务器并检查其当前是否实时
var ws=newwebsocket(“ws://localhost:3000/”;
var计数=0,tempArr=[];
ws.onmessage=函数(消息){
如果(count在您引用的代码中,勾选
函数正在更新图表。听起来您正在运行整个图表创建过程。当然,这是一个猜测,因为您没有显示任何代码……请为您的问题创建一个可复制的示例,否则我们将无法提供帮助。@Mark,我已使用相关代码编辑了问题代码。希望它能帮助您理解这个问题。查看您的代码可以确认这一点,您正在对每个套接字事件运行整个图表创建。您只需要对每个套接字事件运行勾选函数。@标记这一点是有意义的。但是,如果您查看下一个()
函数,它使用变量awesome
,这基本上是我从服务器收到的数据,我不能在套接字之外使用它的值。on方法。嘿,马克。它不打印任何内容,但我将尝试看看我是否可以使用它作为基础。谢谢。更具体地说,变量数据
不保存任何值。它总是空的。变量data
在socket.on方法内有值。但是如果我们在该方法外执行console.log
,则该值不成立。因此图形不会形成,因为它在该方法外。@manuelmourato,对不起,data.shift()
在达到一定数量的点之前不应触发,请参见上文。感谢您的耐心。我已经尝试了您对data.shift()进行修改的代码,但没有成功。正如我昨天所说,这里的问题是,data
变量在套接字中的函数(p)中具有我想要的值。on()方法,但不是在它之外。因此,因为我们在socken.on方法之外创建图形,所以数据变量始终为空,并且无论我们等待data.shift多长时间,图形都无法绘制。您知道我可以用哪种方法解决此问题吗?非常感谢。