在D3中绑定数据时,索引代表什么?

时间:2015-05-27 20:32:57

标签: d3.js data-binding

当我在下面的示例中看到传递给步骤3的数据绑定函数的索引值时,我有点意外:

1)创建两个包装器div,其数据数组绑定到每个

2)创建两个"子div"在每个包装器中,每个

都绑定一个数组

3)将p元素附加到每个" sub-div"

由于元素的嵌套方式,我希望在步骤3中看到0,1的索引传递给数据绑定函数。相反,我看到索引为0,1,2,3。



var data = d3.select("#data");
var idx = d3.select("#indexes");

//---- STEP 1
//create two divs with [1, 4] and [7, 10] bound
var dbox = data.selectAll("tbody").data([[1, 4], [7, 10]]);
dbox.enter().append("div").text(function(d,i){return "Group " + i });
dbox.exit().remove();
dbox.style({"clear":"both","padding":"5px","border":"1px solid #dddddd","overflow":"hidden","margin-bottom":"10px"});

//---- STEP 2
//create sub-divs
var tr = dbox.selectAll("div").data(function(d,i){
  return d.map(function(d,i,a){ return [d, d+1, d+2]; }); //return an array of arrays [[x,y,z], [a,b,c]]
});
tr.enter().append("div").text(function(d,i){return "Index " + i});
tr.exit().remove();
tr.style({"clear":"both","overflow":"hidden","padding":"2px","border":"1px dotted #dddddd","margin-top":"5px"});

//---- STEP 3
//add text (and record indexes in the "INDEXES" section)
//since the tr selection is grouped--with two "tr" divs per "dbox", I expected to see indexes of 0,1 only, instead I see 0, 1, 2, 3.
var td = tr.selectAll("p").data(function(d,i){
  idx.append("p").text(i); //track the indexes
  return d;
})
td.enter().append("p");
td.exit().remove();
td.text(function(d,i){return d}).style({});

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="data">
  
</div>

<div id="indexes" style="clear:both;padding-top:20px;">
  <p>INDEXES</p>
  
</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

我认为这里的混淆是当使用.attr()或.style()等方法对选择进行操作时,传递给function参数的索引表示其父组中元素的索引。

使用.data()方法绑定数据时,传递给function参数的索引表示父元素的索引。这就是Lars在评论中所得到的。

我认为这是有道理的,因为D3选择使用固定的两级层次结构(虽然听起来像change in the future}。因此,当您绑定新数据时,选择的层次结构会发生变化。即父元素不再嵌套在选择中。

这是一个澄清的例子:

&#13;
&#13;
var L1 = d3.select("div#boxes");
L1.append("p").text("Level 1");

var L2 = L1.selectAll("div").data([1,2]);
L2.enter().append("div");

L2.append("p").text(function(d,i){return "Level 2"})

var L3 = L2.selectAll("div").data(function(d,i){
    return [i,i];
});
L3.enter().append("div");
L3.append("p").text(function(d,i){return "Level 3 - Index during data binding: "+d+". Index after appended: "+i+"." })

var L4 = L3.selectAll("div").data(function(d,i){
    return [i,i];
});
L4.enter().append("div");
L4.append("p").text(function(d,i){return "Level 4 - Index during data binding: " +d+". Index after appended: "+i+"."})
&#13;
div{
    padding:5px;
    margin:5px;
    border:1px solid #555555;
}

p{
    font-family:Arial, Helvetica, sans-serif;
    font-size:13px;
}

#indexes p{
    float:left;
    margin-left:5px;
}
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="boxes">
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

selectAll只是将选择中的所有元素提升为父节点(忽略组结构),并将提供的选择器依次应用于每个新的父节点,以在它们上形成新的组。在此之后,在选择前面的父节点中没有引用,该状态丢失。

tr.selectAll("p")tr(2x2 = 4个)中的所有div提升为父节点,并根据绑定到它们的数据形成输入选择。所以有4个组(每个div在tr中有一个),每个组有3个成员(父div上绑定的数据的第一个维度长度为3)。对先前父节点的引用将被丢弃。

如果values selection.data( values中的 ) 是一个函数,那么它是d argument是组父组绑定的数据,i是组索引。

如果 values 不是函数,则相同的数据绑定到每个组。