根据我的理解,更新d3数据的正确方法是将其传递到选择的.data()
。
我获得的数据不是有序的,也不是一致的。所以我非常需要使用更新/添加/删除逻辑。所以d3术语是.data()
.enter()
和.exit()
(对吧?)。
所以我想做的是使用javascript字典而不是数组,其中键是我唯一的标识符。但我似乎无法做到这一点。一个假的例子:
data_one[0] = 'Dogs';
data_one[1] = 'Cats';
d3.selectAll('circle').data(data_one).enter().attr(...)
第二次运行此操作时,我的数据可能相同,但顺序不同。我想用与以前相同的属性来表示它。我不想复制我的代码,但如果我只是做.data(data_two),那么错误的圈子会更新新数据。
有什么方法吗?
答案 0 :(得分:53)
这是键函数的目的,是selection.data的第二个参数:它允许您通过控制哪个数据绑定到哪个元素来维护object constancy。例如,假设您有一组表示水果的对象:
var fruits = [
{name: "orange", value: 200},
{name: "apple", value: 124},
{name: "banana", value: 32}
];
首次创建元素时,您不需要键功能,因为没有任何现有元素,因此您可以使用标准的selectAll-data-enter-append模式:
var div = d3.select("body").selectAll(".fruit")
.data(fruits)
.enter().append("div")
.attr("class", "fruit")
.text(function(d) { return d.name + ": " + d.value; });
此操作的结果是:
<body>
<div class="fruit">orange: 200</div>
<div class="fruit">apple: 124</div>
<div class="fruit">banana: 32</div>
</body>
但现在让我们说您的数据发生了变化,并且您希望更新以反映新数据。这些新数据的顺序可能不同,可能会添加或删除一些元素:
var fruits2 = [
{name: "apple", value: 124},
{name: "lemon", value: 17},
{name: "banana", value: 32},
{name: "strawberry", value: 1465}
];
苹果和香蕉都在原始数据中,因此我们希望保留它们。这称为更新选择。草莓和柠檬是新的;这是输入选项。最后,橙色消失,形成退出选择。
使用引用基准的name
属性的键函数,我们可以按预期将新数据分配给旧元素。然后我们可以创建进入水果并删除现有的水果:
var div = d3.select("body").selectAll(".fruit")
.data(fruits2, function(d) { return d.name; });
div.enter().append("div")
.attr("class", "fruit")
.text(function(d) { return d.name + ": " + d.value; });
div.exit().remove();
这称为general update pattern。 (你可以在第一次这样做;它是selectAll-data-enter-append模式的更一般形式。)结果是:
<body>
<div class="fruit">apple: 124</div>
<div class="fruit">banana: 32</div>
<div class="fruit">lemon: 17</div>
<div class="fruit">strawberry: 1465</div>
</body>
虽然选择div
的顺序与数据fruit2
匹配,但DOM中的顺序不,因为输入的元素已附加到正文的末尾。 (selection.append没有任何花哨的逻辑来保证排序;它只是将新元素附加到父元素的末尾。)当使用SVG时,我们通常不关心DOM元素的顺序,因为所有内容都是绝对定位的。如果您 关心订单,可以在输入后使用selection.order进行修复:
div.order(); // make the DOM element order match the selection
此外,在此示例中,我们不需要对更新选择进行任何更改,因为apple和banana的值没有更改。如果更新数据也发生变化,您可以直接从上面的selection.data调用中对selection.attr和selection.text进行链式调用。