2016-02-10 168 views
0

這個想法是有一個d3垂直條形圖,它將被賦予實時數據。 我模擬實時數據與setInterval函數是更新我的數據集的元素的值:動態更新D3圖表

var updateData = function(){ 
    a = parseInt(Math.random() * 100), 
    b = parseInt(Math.random() * 100), 
    c = parseInt(Math.random() * 100), 
    d = parseInt(Math.random() * 100); 
    dataset = [a, b, c, d]; 
    console.log(dataset); 
}; 

// simullate live data input 
var update = setInterval(updateData, 1000); 

我想更新圖表每2秒。 爲此,我需要一個獲取新數據集的更新函數,然後通過動畫過渡來顯示新結果。 像這樣:

var updateVis = function(){ 
    .......... 
}; 

var updateLoop = setInterval(drawVis,2000); 

我不想簡單地移除圖表並再次繪製。我想爲每個小節的新舊小節高度之間的過渡設置動畫。

結帳的fiddle

回答

1

因爲你不改變酒吧的數量,這可能是那樣簡單:

var updateVis = function(){ 
    svg.selectAll(".input") 
    .data(dataset) 
    .transition() 
    .attr("y", function(d) { 
      return y(d); 
     }) 
     .attr("height", function(d) { 
      return h - y(d); 
    }); 
}; 

更新fiddle

但是,你的下一個問題是,如果我需要不同數量的酒吧呢?這是您需要處理輸入,更新,退出一點的地方。你可以編寫一個函數進行初始繪製或更新。

function drawVis(){ 

// update selection 
var uSel = svg.selectAll(".input") 
     .data(dataset); 

// those exiting 
uSel.exit().remove(); 

// new bars 
uSel 
     .enter() 
     .append("rect") 
     .attr("class", "input") 
     .attr("fill", "rgb(250, 128, 114)"); 

// update all 
uSel 
     .attr("x", function(d, i) { 
      return i * (w/dataset.length) + 2.5/100 * w; 
     }) 
     .attr("width", w/dataset.length - barPadding) 
     .attr("height", y(0)) 
     .transition().duration(750).ease("linear") 
     .attr("y", function(d) { 
      return y(d); 
     }) 
     .attr("height", function(d) { 
      return h - y(d); 
}); 

} 

fiddle

1

這是要走的路。 只要想一想你已經做了什麼來得到初始圖表: 1)獲取數據 2)將它綁定到元素(.enter()) 3)將元素屬性設置爲數據的函數。

那麼,你再次這樣做: 在功能updateData你得到一個新的dataset這是第一步。 然後,重新綁定:

d3.selectAll("rect").data(dataset); 

最後更新的屬性:

d3.selectAll("rect").attr("y", function(d) { 
     return y(d); 
    }) 
    .attr("height", function(d) { 
     return h - y(d); 
    }); 

(想轉換爲它去很容易在你的代碼添加,但你更好地閱讀this tuto如果你想?要深刻認識它)

Check it on fiddle