2016-04-18 3 views
1

を描きます。私は、この例のコードを使用していますグラフを描画するためのは、新しい値が到着すると、私はソケットIOを介してサーバから受信した値を使用しています、と私はリアルタイムで更新チャートを作りたいsocket.on内部D3リアルタイム折れ線グラフ(ソケットIO)

http://jsfiddle.net/chrisJamesC/YruDh/ そして、私は以下のフォームでデータを受け取る:

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

私は私自身の値によってnext()機能でvalueフィールドを置き換え、つまりソケットから受け取った値はすべて素晴らしいです。

唯一の問題は、新しいデータポイントが到着するたびに、グラフが更新されるだけでなく、既存のグラフの下の同じグラフの正確なコピーがブラウザに表示されることです。これは、新しいデータポイントを受け取るたびに、ブラウザに20以上のグラフがあり、ある時点でクラッシュするまで続きます。

socket.onの外でチャートを作成しようとしましたが、上記の例のようにランダムデータを使用しても、何も表示されません。だから、私は、グラフを作成し、それを2秒ごとに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(); 

} 

}); 

ありがとうございました。

+0

は、チャートを更新しています。あなたがチャート作成全体を再実行しているように思えます。これはもちろん、コードを表示していないため推測です...問題の再現可能な例を作成してください。それ以外の場合は手助けできません。 – Mark

+0

@マーク、関連するコードで質問を編集しました。あなたがその問題を理解するのを助けてくれると嬉しいです。 –

+0

コードを確認すると、各ソケットイベントでチャート作成全体が再実行されます。各ソケットイベントに対して 'tick'関数を実行するだけです。 – Mark

答えて

2

完全にテストされていないコードがありますが、このような何かを再構築する必要があります。

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

}); 
+0

Hey Mark。それは何も印刷されませんが、私はそれがベースとしてこれを使用して動作させることができるかどうかを確認しようとします。ありがとうございました。 –

+0

具体的には、変数 'data'は値を保存しません。それは常に空です。 –

+0

変数 'data'はsocket.onメソッドの中にある値を持ちます。しかし、そのメソッドの外で 'console.log'を実行すると、同じことは成立しません。したがって、メソッドの外側にあるためグラフィックは形成されません。 –

0

私はWS用WebSocketを使用してD3とプロットこのリアルタイムを実装している、あなたはそれをチェックアウトすることができ、これはスクリプトである、あなたはまた、ここにHTMLを持っていますが、追加されていない、しかも、このD3ファイルを提供していますだけでなく、ランダムなJSONを生成するサーバーがある、このサーバーを作成することができ、時間のためにそのリアルタイムの

<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));
ているかどうかをチェックしますあなたは `tick`機能を参照するコードでは

関連する問題