0

我对此完全感到困惑。我在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}]会生成一个 2x2 网格。div.item

现在,当我更改数据以data = [{b},{a}]使我感到困惑时会发生什么。数据连接后,items如下所示:

[Array[2]
0: div.item
1: div.item
length: 2
parentNode: div#data
__proto__: Array[0]
]

__data__of div.item0 指向 object ,我认为这是正确的{b},但是我不能使第一个和第二个元素交换位置,因为它们“忘记”了它们的旧位置。

另一种情况:假设我将原始数据更改为data = [{b},{a},{e}],即我引入了一个新元素{e}。然后我想交换前两个元素(带有过渡)并首先删除第三个元素({c})并淡入新的第三个元素({e})。这甚至可能吗?我做错了什么/我误解了什么?

4

2 回答 2

1

我建议阅读选择如何工作

您的示例与原始示例不同,因为您在绑定数据时没有使用键功能。如果您不指定键函数,它将默认使用元素的位置(索引)来确定哪些元素是相同的(因此应该保留以供更新选择),以及应该添加/删除哪些元素。

文档中:

如果未指定键功能,则将指定数组中的第一个数据分配给当前选择中的第一个元素,将第二个数据分配给第二个选定元素,依此类推。

因此,我建议使用 key 函数,以便在绑定新数据时添加、更新和删除正确的元素。

于 2013-06-13T09:18:44.183 回答
0

在阅读了更多问题和示例后,我发现问题与对象恒定性有关(请参阅http://bost.ocks.org/mike/constancy/)。我必须在函数中指定某个键data

items = items.data(data, function(d){ return d.key; );
于 2013-06-13T09:17:51.443 回答