2016-05-27 68 views
0

我是d3.js的新手,正在努力通過「D3.js in action」一書。到目前爲止,我已經能夠弄清楚我所有的問題,但似乎我無法完全回答這個問題。D3數據綁定[D3js in Action]

我在這裏發佈這本書的源代碼,因爲它可以在書籍網站和作者主頁上找到。這是bl.ocks:http://bl.ocks.org/emeeks/raw/186d62271bb3069446b5/

該代碼的基本思想是創建一個電子表格樣佈局,充滿虛擬twitter數據的div元素。還實現了一個排序功能,通過時間戳對數據進行排序並對錶單重新排序。以及重建原始訂單的功能。

下面是代碼(我離開了那裏創建表結構,除了部分在數據綁定的一部分):

<html> 
<...> 
<body> 
<div id="traditional"> 
</div> 
</body> 
    <footer> 

<script> 
d3.json("tweets.json",function(error,data) { createSpreadsheet(data.tweets)}); 

     function createSpreadsheet(incData) { 

     var keyValues = d3.keys(incData[0]) 

     d3.select("div.table") 
     .selectAll("div.datarow") 
     .data(incData, function(d) {return d.content}) 
     .enter() 
     .append("div") 
     .attr("class", "datarow") 
     .style("top", function(d,i) {return (40 + (i * 40)) + "px"}); 

     d3.selectAll("div.datarow") 
     .selectAll("div.data") 
     .data(function(d) {return d3.entries(d)}) 
     .enter() 
     .append("div") 
     .attr("class", "data") 
     .html(function (d) {return d.value}) 
     .style("left", function(d,i,j) {return (i * 100) + "px"}); 

     d3.select("#traditional").insert("button", ".table") 
     .on("click", sortSheet).html("sort") 
     d3.select("#traditional").insert("button", ".table") 
     .on("click", restoreSheet).html("restore") 

function sortSheet() { 
      var dataset = d3.selectAll("div.datarow").data(); 
      dataset.sort(function(a,b) { 
       var a = new Date(a.timestamp); 
       var b = new Date(b.timestamp); 
      return a>=b ? 1 : (a<b ? -1 : 0); 
      }) 
      d3.selectAll("div.datarow") 
      .data(dataset, function(d) {return d.content}) 
      .transition() 
      .duration(2000) 
      .style("top", function(d,i) {return (40 + (i * 40)) + "px"}); 
     } 

     function restoreSheet() { 
      d3.selectAll("div.datarow") 
      .transition() 
      .duration(2000) 
      .style("top", function(d,i) {return (40 + (i * 40)) + "px"}); 
     } 
     } 
</script> 
    </footer> 
</html> 

我不完全明白是怎麼sortSheet和restoreSheet工作。

sortSheet的這部分看起來像重新綁定數據,但在控制檯日誌記錄之後,我認爲它實際上並沒有將數據重新綁定到DOM。相反,它似乎根據排序數組的數組索引來重繪div.tablerow元素。

但是關鍵功能有什麼用途? 爲什麼過渡工作?它如何知道哪個元素放在哪個新位置?

編輯: ---經過一些更多的閱讀我現在知道selectAll().data()確實會返回更新選擇。顯然,由鍵功能標識的已經綁定的數據被重新排序以匹配新數據集中的鍵的順序?那是對的嗎? 因此,更新選擇包含現有的div.datarow,但以新的順序。 transition()函數對新訂單起作用,繪製新訂購的div.datarow,以索引0開始,爲第一個元素確定其在頁面上的位置,以便爲最後一個元素索引n。圖形過渡然後以某種方式(如何?通過更新選擇的方式?)知道重畫div.datarow之前,並創建過渡效果。 目前爲止是否正確?---

d3.selectAll("div.datarow") 
.data(dataset, function(d) {return d.content}) //why the key function? 
.transition() 
.duration(2000) 
.style("top", function(d,i) {return (40 + (i * 40)) + "px"}); 

當原始訂單恢復時會發生什麼?顯然,在這兩個操作中,沒有實際的數據重新綁定,並且DOM中的順序不會改變。因此還原功能還會根據數組索引重新繪製佈局。 但.transition()的工作原理是什麼? 這是更新嗎?這是一個更新。 爲什麼使用索引結果繪製舊佈局? 不應該DOM元素的索引總是爲0,1,...,n?我認爲這是。顯然,舊的頁面佈局被重繪,DOM從未改變過。但是,transition()函數如何創建適當的圖形效果?

function restoreSheet() { 
d3.selectAll("div.datarow") 
.transition() 
.duration(2000) 
.style("top", function(d,i) {return (40 + (i * 40)) + "px"}); 
} 

我一直在想這幾個小時,但我找不到正確的答案,我想。 感謝您的幫助!

回答

0

當你理解所有這些函數被調用的地方時,這一切都變得清晰了:在json函數中,數據最初是綁定的。當一個按鈕調用sortSheet函數時,會創建一個新的對象數組並綁定到這些行。轉換隻需從原始順序開始,並根據數組內對象的新順序移動行。

當原始訂單被恢復時會發生什麼?

現在到了最有趣的部分:restoreSheet稱爲json函數內部,並具有對dataset變量的訪問權限。所以,數據restoreSheet使用的是原始數據。然後,過渡只根據原始數組內的對象的順序來移動行。

我剛剛作出了一個小提琴複製此:https://jsfiddle.net/k9012vro/2/

檢查代碼:我有與原始數據陣列。然後,一個名爲「sort」的按鈕創建一個新的數組。

當我點擊「原始」矩形移回原來的位置。但並沒有什麼特殊之處在於功能,沒有新的數據被綁定:

d3.select("#button1").on("click", function(){ 
    rects.transition() 
    .duration(500).attr("x", function(d, i){ return i * 30}) 
}); 

它會將所有的矩形到原來的位置,因爲該功能使用相同的原始data