在socket.on中绘制一个d3实时线图(socket io) [英] Drawing a d3 realtime line chart inside socket.on (socket io)

查看:158
本文介绍了在socket.on中绘制一个d3实时线图(socket io)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用通过套接字io从服务器接收到的值,并且我想创建一个图表,在新值到达时实时更新。



绘制图表我使用的示例代码: http://jsfiddle.net/chrisJamesC/YruDh/
我收到以下形式的数据:

  socket.on('news',function数据){/ *我在这里的图表* / ...}); 

我替换了 code> next()函数由我自己的值,也就是我从套接字收到的值,一切都很好。



唯一的问题是,每当一个新的数据点到达时,每两秒钟,不仅图形被更新,但我得到一个完全相同的图表的副本浏览器,下面已经存在的图。这种情况每当我收到一个新的数据点,直到最终我有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基础)
.x(function(d,i){return x(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 b $ b .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 +))
.call(x.axis = xAxis); * /

var path = svg.append(g)
.attr(clip-path,url(#clip))
.append路径)
.data([data])
.attr(class,line);

tick();

function tick(){

//更新域
x.domain([t - n + 2,t]);

//将累计计数推到后面,并重置计数
data.push(next());

//重绘行
svg.select(。line)
.attr(d,line)
.attr空值);

//向左滑动x轴
axis.transition()
.duration(duration)
.ease(linear)
。 call(x.axis);

//向左滑动一行
path.transition()
.duration(duration)
.ease(linear)
.attr transform,translate(+ x(tn)+))


//从前面弹出旧数据点
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 b $ b .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 +))
.call(x.axis = xAxis); * /

var path = svg.append(g)
.attr(clip-path,url(#clip))
.append路径)
.data([data])
.attr(class,line);

function tick(){

//更新域
x.domain([t - n + 2,t]);

//重绘行
svg.select(。line)
.attr(d,line)
.attr空值);

//向左滑动x轴
axis.transition()
.duration(duration)
.ease(linear)
。 call(x.axis);

//向左滑动一行
path.transition()
.duration(duration)
.ease(linear)
.attr transform,translate(+ x(t-n)+));

//从前面弹出旧数据点
if(data.length> 40)data.shift();

}

socket.on('news',function(p){

p = JSON.parse(p);
data.push({
time:++ t,
value:p.valuee
})

tick();

});


I am using values that I receive from a server via socket io, and I want to make a chart that updates in realtime, as new values arrive.

For drawing the graph I am using the code from this example: http://jsfiddle.net/chrisJamesC/YruDh/ And I receive the data in the form below:

 socket.on('news', function (data) { /*I make the chart here*/...});

I replaced the value field in the next() function by my own values, that is, the values I receive from the socket , and everything works great.

The only problem is that, everytime a new data point arrives, every two seconds, not only the graph gets updated, but I get an exact copy of the same chart in the browser, below the already existing graph. This continues to happen everytime I receive a new data point, until eventually I have 20 or more charts in my browser, causing it to crash at some point.

I tried to create the chart outside of socket.on, even using random data exactly as it is in the example above, and it doesn't show anything. So I assume that I need to create the graph and update it every two seconds in the socket.on() method. How can I create and update the chart without making multiple copies of it?

Here is the full code I have now:

 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();

}

});

Thank you so much.

解决方案

Completely untested code, but you need to restructure to something like this:

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();

});

这篇关于在socket.on中绘制一个d3实时线图(socket io)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆