作为d3和javascript的新手,我试图通过查看
提供的版本来了解可折叠树的工作原理http://bl.ocks.org/mbostock/4339083
具体来说,我不明白在更新节点后,以下语句如何以及为何成功为节点分配唯一ID。
//更新节点......
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
我的理解是节点是一个数组,这个数组有一个相关的索引i。 每次更新节点时,上述语句使用从数组索引i派生的id的唯一键值将新节点(如在数据中)与网页上的节点(如在可视表示中)绑定。如果nodes数组的元素没有id,则会为其分配++ i。
这是我感到困惑的地方。假设第一个节点数组有4个元素,因此每个元素的id为1,2,3和4.我折叠树,现在新节点数组有3个元素恰好是第一个节点的前三个元素阵列。这些元素的id为1,2和3.到目前为止没问题。
现在,下一个更新的节点数组有4个元素,前3个元素相同,第4个元素不同。 上面的代码正确地为第4个元素指定了一个id为5。
我的理解是
这最后一个节点数组有4个元素,
索引i为这个新的第4个元素= 3,
++ i = 4
因此,上述陈述应该为第4个元素指定了4的id。
但代码指定了id = 5。当我在firebug调试器中检查i的值时,我上升到4,保持在4,然后在上面的场景中变为5。
有人可以用上面的代码解释发生了什么,以及我的错误理解在哪里?
谢谢。
答案 0 :(得分:1)
您所指的特定示例中使用的变量i
与几乎所有其他D3示例相反,是一个全局计数器,用于跟踪已查看的节点数。在许多其他情况下,您会看到像
.attr("something", function(d, i) { ... })
或
.data(data, function(d, i) { ... })
在所有这些情况下,i
引用函数的局部变量 - 其数组中的数据元素的索引。这是由D3和完全不同的 i
传递的,而不是您所指的示例中的。{/ p>
如果将所有i
替换为counter
,可能会更好地理解该示例。
答案 1 :(得分:0)
您可以使用以下内容为可折叠树中的节点分配唯一ID :
.attr('id', function() { return('node_' + makeid()) })
这里我使用Azle中的az.makeid()函数,但你可以使用你喜欢的任何东西来生成唯一的id。
我们将此添加到nodeEnter.append('circle')函数中,如下所示:
// Add Circle for the nodes
nodeEnter.append('circle').
attr('class', 'node').
attr('r', 10).
style("fill", function(d) {return "#33AADE"})
.attr('id', function() { return('node_' + makeid()) }) // add id here
在每个节点上使用唯一ID,我们释放各种附加功能,允许我们将其他库与D3一起使用。例如,当用户点击节点时,我们可以使用Azle来颜色并为特定节点制作动画:
svg.selectAll("circle")
.on("click", function(d) {
var selected_circles = d3.select(this);
selected_id = selected_circles._groups[0][0].id;
az.animate_element('node', get_target_instance(selected_id), {
"type" : "rubberBand"
})
az.delay_event({
"function" : "$('#' + selected_id).css('fill', 'hotpink')"
})
});
结果:
飞走动画: