Dibujar un gráfico de líneas en tiempo real d3 dentro de socket.on (socket io)

Estoy usando los valores que recibo de un servidor a través de socket io, y quiero hacer un gráfico que se actualice en tiempo real, a medida que lleguen los nuevos valores.

Para dibujar el gráfico, estoy usando el código de este ejemplo: http://jsfiddle.net/chrisJamesC/YruDh/ Y recibo los datos en el siguiente formulario:

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

Reemplazé el campo de value en la función next() por mis propios valores, es decir, los valores que recibo del socket, y todo funciona muy bien.

El único problema es que, cada vez que llega un nuevo punto de datos, cada dos segundos, no solo se actualiza el gráfico, sino que también se obtiene una copia exacta del mismo gráfico en el navegador, debajo del gráfico ya existente. Esto sigue ocurriendo cada vez que recibo un nuevo punto de datos, hasta que finalmente tengo 20 o más gráficos en mi navegador, lo que provoca que se bloquee en algún momento.

Intenté crear el gráfico fuera de socket.on , incluso utilizando datos aleatorios exactamente como se muestra en el ejemplo anterior, y no muestra nada. Así que asumo que necesito crear el gráfico y actualizarlo cada dos segundos en el método socket.on (). ¿Cómo puedo crear y actualizar el gráfico sin hacer varias copias?

Aquí está el código completo que tengo ahora:

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

Muchas gracias.

Código completamente no probado, pero necesita reestructurarse a algo como esto:

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

He implementado este trazado en tiempo real con D3 usando ws websocket, puede verificarlo, este es el script, también tendrá html aquí, pero no agregado, además, hay un servidor que sirve este archivo d3 y genera json aleatorio, puede crear este servidor y verificar si es en tiempo real