2016-05-27 53 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