我对此完全感到困惑。我用http://bl.ocks.org/mbostock/raw/3808234/处的字母查看了示例,其中更新的元素根据数据集中字母的位置更改其位置。
现在我想重现类似的东西,但是使用div元素('.item's
)。到目前为止,我有:
var displayData = function() {
// DATA JOIN
var items = d3.select('#data').selectAll('.item');
items = items.data(data);
// UPDATE
items.transition().duration(500)
.style('left', function(d, i) {
return positions[i].left + "px";
}).style('top', function(d, i) {
return positions[i].top + "px";
});
// ENTER
var div = items.enter().append('div')
.attr('class', 'item')
.style('left', function(d, i) {
return positions[i].left + "px";
}).style('top', function(d, i) {
return positions[i].top + "px";
})
.style('opacity', 1e-6)
.transition().duration(TRANSITION_DURATION)
.style('opacity', 1);
// EXIT
items.exit().transition().duration(500).style('opacity', 0).remove();
}
positions
是具有预先计算位置的简单对象数组(它们根据屏幕大小而变化),例如:
positions =
[{left: 0, top: 0},
{left: 240, top: 0},
{left: 0, top: 360},
{left: 240, top: 360}]
因此,给定一个包含四个数据对象data = [{a},{b},{c},{d}]
的数组,上面的代码在第一次调用时会生成div.item
的2x2网格。
现在当我将数据更改为data = [{b},{a}]
时会发生什么事让我困惑。数据加入后,items
如下所示:
[Array[2]
0: div.item
1: div.item
length: 2
parentNode: div#data
__proto__: Array[0]
]
__data__
div.item
0指向对象{b}
,我认为这是正确的,但是我不能让第一个和第二个元素交换位置,因为它们"忘记"他们的旧职位。
另一种情况:我们说我将原始数据更改为data = [{b},{a},{e}]
,即我引入了一个新元素{e}
。然后我想交换前两个元素(带过渡)并首先删除第三个元素({c}
)并淡入新的第三个元素({e}
)。这甚至可能吗?我做错了什么/我误解了什么?
答案 0 :(得分:1)
我建议您阅读How Selections Work。
您的示例与原始示例不同,因为您在绑定数据时未使用键功能。如果未指定键函数,则默认使用元素的位置(索引)来确定哪些元素相同(因此应保留用于更新选择),以及应添加/删除哪些元素。
如果未指定键功能,则指定数组中的第一个数据将分配给当前选择中的第一个元素,第二个数据分配给第二个选定元素,依此类推。
因此,我建议使用键功能,以便在绑定新数据时添加,更新和删除正确的元素。
答案 1 :(得分:0)
在阅读了一些问题和示例之后,我发现问题与对象恒定性有关(参见http://bost.ocks.org/mike/constancy/)。我必须在data
函数中指定某个键:
items = items.data(data, function(d){ return d.key; );