2012-12-07 28 views
0

我正在使用d3庫來繪製帶有通過websockets從服務器接收到的JSON對象的條形圖。但是,發生的情況是,每次繪製圖形時都會繪製一個圖形的新實例。所以我結束了多個圖表。關於圖的多個實例的圖

但我希望JSON數據全部繪製在同一張圖上。

這裏是我的代碼:

 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無法實時處理數據並相應更新圖表,或者如果沒有明確的教程/如何解釋。

感謝

回答

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); 
} 
+0

感謝您的回覆。我嘗試過,現在只繪製一次圖表,但沒有用新數據更新該圖表。 – user94628

+0

也許是因爲高度只能設置一次。可能需要在if語句之外執行'chart.attr('height',20 * useData.length)' –

+0

將if語句之外的chart.attr('height',20 * useData.length)放在if語句之外。 – user94628

0

就像Brian說的,你在每一個onmessage事件中都會創建一個新的svg元素。但是,在D3中,不需要使用if語句來檢查元素的存在;你做一個數據連接之後,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; }); 

數據的概念加入,輸入(),更新(),並退出()選項的解釋在Thing with Joins文章中。另見3 General Update Pattern文章。

當您在圖表中更新或添加新的矩形元素時,您必須使用類似的方法。假設該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中給出。

+0

非常感謝....當我運行它時,控制檯日誌中出現「ReferenceError:y未定義」。正如你所說,你不知道我的數據結構是什麼樣子。這很簡單,useData只是一個數組的數組,例如:[1,2,3,5,8,13,21,34,55,89]。我將如何擺脫參考錯誤? – user94628

+0

y函數是你的序數量表......你有一個jsfiddle或你可以分享的東西嗎?圖表部分,沒有websocket的東西。 – nautat

+0

它位於http://jsfiddle.net/2NXF2/2/。謝謝 – user94628