2013-12-20 127 views
2

使用d3.js通過獲取100個對象的數組繪製一系列矩形。儘管console.log(data)顯示正在檢索新數據,但新數據點似乎沒有附加任何矩形。d3.js圖表​​未更新新數據

.enter().append()使用不正確?

function init() { 
    var width = 800, 
     height = 400, 
     margin = 50; 

    chart = d3.select('#chart') 
       .append('svg:svg') 
       .attr('width', width) 
       .attr('height', height); 
} 

function do_update() { 
    data = fetch_latest_top100(); 
    console.log(data) 

    chart.selectAll('rect') 
     .data(data) 
     .enter() 
     .append('svg:rect') 
     .attr('x', function(d) { return x(d.x); }) 
     .attr('y', function(d) { return y(d.y); }) 
     .attr('height', function(d) { return d.value; }) 
     .attr('width', function(d) { return 3 }); 
} 

的jsfiddlehttp://jsfiddle.net/BU8cA/

+0

這將是更好,如果你有一個小提琴(http://jsfiddle.net/)或plunkr http://plnkr.co/edit/?p=catalogue這將有助於看到問題生活 –

+0

我不知道這是一個複製/粘貼的問題,但你錯過了一個「)」之後y(dy在y attr,這可能是錯誤 – tomtomtom

+0

@tomtomtom複製粘貼問題,更正了錯字,謝謝! – Nyxynyx

回答

11

與更新方法的問題是,它只能處理新的元素,並且不更新現有的元素,以滿足他們新的數據。使用enter()選擇創建新矩形後,必須返回完整選擇(新的和變化的矩形)以設置要更改的屬性。

要做到這一點,最簡單的方法是選擇存儲在一個變量在您應用了數據功能點,但在打電話之前的輸入法,如:

var rects = chart.selectAll('rect') 
     .data(data); 

    rects.enter() 
     .append('svg:rect') 
     .attr('width', function(d) { return 3 }); 
     // since the width is constant, you only need to set it once 

    rects.exit().remove(); //if the number of data points might shrink 

    rects.attr('x', function(d) { return x(d.x); }) 
     .attr('y', function(d) { return y(d.y); }) 
     .attr('height', function(d) { return d.value; }); 
    //note that this now includes the rectangles created with enter() 
    //as well as the old ones you are resizing/repositioning 

這應該得到正確的數據,但你仍然有一個佈局問題(無論如何,在小提琴),因爲你的y值沒有被正確設置。 y值是矩形頂部的位置,所以如果您想要看起來像是全部坐在同一條線上的酒吧,則需要根據酒吧的高度進行調整。邁克·博斯托克的教程和演示在這裏:http://bost.ocks.org/mike/bar/3/


更新版本的D3 4+

元素附加到「輸入」選擇不再自動添加到主(更新)選擇。現在,您需要明確地創建一個「合併」選項,通過調用「輸入」選擇merge方法:

var rects = chart.selectAll('rect') 
    .data(data); 

rects.exit().remove(); //if the number of data points might shrink 

rects.enter() 
    .append('svg:rect') 
    .attr('width', function(d) { return 3 }) // since the width is constant, you only need to set it once 

    .merge(rects) 
      //merge the newly added elements into the main selection 
      //of existing elements to update 
    .attr('x', function(d) { return x(d.x); }) 
    .attr('y', function(d) { return y(d.y); }) 
    .attr('height', function(d) { return d.value; }); 
+0

這個答案仍然有效嗎?如果在調用rects.enter()。append()之後調用rects.nodes(),我仍然會返回一個空數組。如果上面的聲明「現在包含使用enter()創建的矩形」是真實的,那麼我是否應該看到一個已填充的數組,而不是在調用.nodes()時的空數組? – MattEvansDev

+1

@mevans您是否在使用D3 v4?它改變了合併的工作方式,請參閱[Mike Bostock關於更改背後推理的概述](https://medium.com/@mbostock/what-makes-software-good-943557f8a488)。您現在需要顯式調用'selection.merge()'來合併輸入和更新選擇。 – AmeliaBR

+0

是的 - 我正在使用D3 v4。 .merge()的引入和輸入/更新(現在的功能與網絡上的大多數示例相反)的變化令人生氣。非常感謝澄清。 – MattEvansDev