2014-03-31 113 views
2

我在這一個瘋狂......
第一次調用時,refreshGraph()完美工作:顯示我的圖形。
在下面的調用中,沒有任何反應。 selectAll()按照預期返回一個數組數組,,但是我的圖不會改變
但是...如果我使用select()而不是selectAll(),它的工作原理!
AND WORST ...如果我在join.selectAll(「.bar」)之前添加了join.select(「.bar」),它也可以工作!selectAll只能在D3中運行一次

任何人都可以解釋我爲什麼?

我不明白這種行爲。我完全理解select()和selectAll()會返回什麼。在兩個返回的子集上調用style()應該給出相同的結果,因爲數據是相同的,即使按組按selectAll組織並且使用select保持平坦。我對嗎 ?

var srcData = [4, 8, 15, 16, 23, 42]; 

x = d3.scale.linear().domain([0, 42]).range([0, 420]); 

function refreshGraph() { 

    join = d3.select(".chart").selectAll(".container").data(srcData); 

    join.enter() 
    .append("span").attr("class","container") 
    .append("div").attr("class","bar"); 

    join 
    .selectAll(".bar") // wont work, but will if select() instead of selectAll() 
    .style("width", function(d) { 
     return x(d) + "px"; 
    }); 
} 

function doChange() { 
    for (var i = 0; i < srcData.length; i++) { 
     srcData[i] /= 2; 
    } 
    refreshGraph(); 
} 

refreshGraph(); 

回答

1

這裏的問題是當數據被綁定到子元素。當你調用.selectAll('.container').data(srcData)

  • .container元素的初始數據綁定,並在每次重新調用時重新綁定用新的數據。

  • .bar元素的數據綁定在創造,當他們追加到.container元素,但是當你新的數據綁定到.container反彈。

的解決辦法是強行.bar數據每次調用refreshData時間重新綁定到它的父:

join 
    .selectAll(".bar") 
    .data(function(d) { return [d]; }) 
    .style("width", function(d) { 
     return x(d) + "px"; 
    }); 
+0

但我refreshGraph()與d3.select( 「圖 」)開始。全選(「 容器」)。數據(srcData)。每次調用函數時,數據都會被綁定到.container元素。然後通過join.enter()添加缺失的節點,但樣式尚未應用。它應該由join.selectAll(「酒吧」)...這意味着設置‘您可以通過.container所有的.bar歸類元素(連接選擇),並應用這種風格’。另外,它將使用select()!爲什麼? – user3173982

+0

.select()將父數據綁定到子級。但它只是一個單元素選擇,所以在這種情況下它不會起作用。 – nrabinowitz

2

小時後和讀取文檔,並步入D3代碼小時,我終於得到它。我結合了幾個案例,這導致了一堆混亂。 那麼,這是什麼?

join = d3.select(".chart").selectAll(".container").data(srcData); 
join.enter() 
.append("span").attr("class","container") 
.append("div").attr("class","bar"); 

append()功能做一些其它事情棘手,以幫助您:

追加與指定的名稱作爲當前選擇的每個元素的最後一個子一個新的元素,返回包含附加元素的新選擇。 每個新元素都以與選擇子選擇相同的方式繼承當前元素的數據(如果有)。

但是... 繼承這個詞是誤導性的。你必須閱讀:每個新元素接收拷貝數據的從目前的元素

隨着D3的工作方式,也沒有神奇的結合。每次您想要反映值的更改時,都會以同樣的方式重新綁定數據,您必須將數據設置在正確的節點中。 append()函數爲你完成了這項工作,select()函數也可以這樣做,但selectAll()不是。

對於當前選擇的每個元素,選擇匹配指定選擇字符串派生元素。 ... 子選擇不會繼承當前選擇的數據;

在我的問題代碼中,在第一次調用時,數據通過append()從.container複製到.bar元素。由於數據不量的變化(沒有新的/沒少值),則後續調用繞過的append()函數(輸入()部分爲空)和全選()將得到正確的節點(的.bar入級)仍有以前的數據版本。當調用style()時,這不是應用的新數據。

,當然還有,使用select()做它的工作原理,因爲它從祖先中的數據複製到部分選定的元素。

nrabinowitz能得到正確的anwser:如果你是絕對要使用全選,你必須使用一個函數來檢索分組節點的數據。

全選()醫生說:返回的選擇由祖先節點當前所選分組...如果數據值被指定爲一個函數,該函數將被用的數據d稱爲祖先節點和組索引i來確定子選擇的數據綁定。

希望這將有助於...