0

d3 ライブラリを使用して、websocket を介してサーバーから受信した JSON オブジェクトを棒グラフにプロットしています。ただし、グラフがプロットされるたびに、グラフの新しいインスタンスが描画されます。だから私は複数のグラフになってしまいます。

しかし、JSON データをすべて同じ 1 つのグラフにプロットしたいと考えています。

これが私のコードです:

      ws = new WebSocket("ws://localhost:8888/dh");

      var useData = []
      //var chart;

      var chart = d3.select("body")
         .append("svg:svg")
         .attr("class", "chart")
         .attr("width", 420)
         .attr("height", 200);


      ws.onmessage = function(evt)
      {  
        var distances = JSON.parse(evt.data);
        data  = distances.miles;
        console.log(data);

        if(useData.length <= 10){
          useData.push(data)
        }
        else
        {

           var draw = function(data){        
           // Set the width relative to max data value
           var x = d3.scale.linear()
            .domain([0, d3.max(useData)])
            .range([0, 420]);

           var y = d3.scale.ordinal()
            .domain(useData)
            .rangeBands([0, 120]);

           var rect = chart.selectAll("rect")
            .data(useData)

            // enter rect
            rect.enter().append("svg:rect")
                .attr("y", y)
                .attr("width", x)
                .attr("height", y.rangeBand());

            // update rect            
            rect
                .attr("y", y)
                .attr("width", x)
                .attr("height", y.rangeBand());

           var text = chart.selectAll("text")
                .data(useData)

           // enter text
           text.enter().append("svg:text")
                .attr("x", x)
                .attr("y", function (d) { return y(d) + y.rangeBand() / 2; })
                .attr("dx", -3) // padding-right
                .attr("dy", ".35em") // vertical-align: middle
                .attr("text-anchor", "end") // text-align: right
                .text(String);

            // update text
            text
                .data(useData)
                .attr("x", x)
                .text(String);
        }
    useData.length = 0;
       }          
    }                 

常に更新されているグラフにすべてのポイントをプロットするにはどうすればよいですか?

d3がリアルタイムでデータを処理できず、それに応じてチャートを更新できないこと、または可能であれば、その方法に関する明確なチュートリアル/説明がないことは残念です.

ありがとう

4

2 に答える 2

0

私の推測では、毎回次のようにチャートを作成しているためです。

var chart = d3.select("body")
.append("svg:svg")
.attr("class", "chart")
.attr("width", 420)
.attr("height", 20 * useData.length);

むしろ、チャートが存在するかどうかを確認する必要があり、存在する場合はその行を呼び出さないでください。

// outside of .onmessage
var chart;

// inside of .onmessage
if (!chart) {
    chart = d3.select("body")
    .append("svg:svg")
    .attr("class", "chart")
    .attr("width", 420)
    .attr("height", 20 * useData.length);
}
于 2012-12-07T22:15:36.993 に答える
0

ブライアンが言ったようsvgに、onmessage イベントごとに新しい要素を作成し続けます。ifただし、D3 では、ステートメントを使用して要素の存在を確認する必要はありません。データ結合を実行すると、enter()選択にはまだ存在していなかった要素のみが含まれます。

// data join
var chart = d3.select("body").selectAll(".chart")
    .data([useData]); // if you wanted multiple charts: .data([useData1, useDate2, useData3])

// enter
chart.enter().append("svg") // this will only execute if the .chart did not exist yet
    .attr("class", "chart")
    .attr("width", 420);

// update (both new and existing charts)
chart
    .attr("height", function(d) { return 20 * d.length; });

データ結合、enter()、update()、および exit() の選択の概念については、Thing with Joinsの記事で説明されています。3 つの一般的な更新パターンの記事も参照してください。

チャートで新しい rect 要素を更新または追加するときは、同様のアプローチを使用する必要があります。今のところ、useData に蓄積されたすべてのデータが含まれていると仮定します (ただし、useData.length = 0 はそうではないことを意味する場合があります)。

// data join
var rects = chart.selectAll("rect")
    .data(function(d) { return d; }); // use the data bound to each chart

// enter
rects.enter().append("rect");

// update
rects
    .attr("y", function(d) { return y(d.yValue); }) // not sure what your data structure looks like
    .attr("width", function(d) { return x(d.xValue); })
    .attr("height", y.rangeBand());

// exit
rects.exit().remove();

リアルタイム データでパスを更新する方法のいくつかの提案は、Path Transitionsに記載されています。

于 2012-12-08T17:28:54.827 に答える