在socket.on(socket io)中绘制d3实时线形图

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

对于绘制图我使用这个例子中的代码: http : //jsfiddle.net/chrisJamesC/YruDh/然后我收到下面的表格中的数据:

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

我用我自己的值replacenext()函数中的value字段,也就是我从套接字接收的值,并且一切都很好。

唯一的问题是,每当一个新的数据点到达,每隔两秒钟,不仅图表得到更新,而且还会在浏览器中获得相同图表的精确副本,在已经存在的图表下方。 每当我收到一个新的数据点时,这种情况就会持续发生,直到最终我的浏览器中有20个或更多的图表,导致它在某个时候崩溃。

我试图在socket.on之外创build图表,即使使用上面示例中的随机数据,也不会显示任何内容。 所以我假设我需要创build图并在socket.on()方法中每两秒更新一次。 如何创build和更新图表,而不需要创build多个副本?

这里是我现在的完整代码:

  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(tn) + ")") .each("end", tick); // pop the old data point off the front data.shift(); } }); 

非常感谢。

完全未经testing的代码,但你需要重构为这样的东西:

 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,你可以创build这个服务器,并检查它的实时性

 <script src="https://cdn.socket.io/socket.io-1.4.5.js"></script> </div> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> var ws = new WebSocket("ws://localhost:3000/"); var count = 0, tempArr = []; ws.onmessage = function (message) { if(count<10) { tempArr.push(JSON.parse(message.data)); count++; } init(); } function init(){ var vis = d3.select("#visualisation"), WIDTH = 1000, HEIGHT = 500, MARGINS = { top: 20, right: 20, bottom: 20, left: 50 }, xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([2000, 2010]), yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([134, 215]), xAxis = d3.svg.axis() .scale(xScale), yAxis = d3.svg.axis() .scale(yScale) .orient("left"); vis.append("svg:g") .attr("class", "x axis") .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")") .call(xAxis); vis.append("svg:g") .attr("class", "y axis") .attr("transform", "translate(" + (MARGINS.left) + ",0)") .call(yAxis); var lineGen = d3.svg.line() .x(function(d) { return xScale(d.year); }) .y(function(d) { return yScale(d.sale); }) .interpolate("basis"); vis.append('svg:path') //.enter() .attr('d', lineGen(tempArr/*data*/)) //.attr('d', lineGen(obj.year)) .transition() .duration(1000) //.delay(2000) .attr('stroke', 'green') .attr('stroke-width', 2) .attr('fill', 'none'); console.log(JSON.parse(message.data));