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