gpt4 book ai didi

d3.js - D3 变化检测是如何工作的?

转载 作者:行者123 更新时间:2023-12-05 08:42:11 26 4
gpt4 key购买 nike

如果我有一个 JSON 对象数组。 D3 如何确定哪些进入 enter() 集合?

如果我有一个对象数组,像这样:

var data = [
{label:'a', value:1},
{label:'b', value:3},
{label:'c', value:2}
]

然后我将它绑定(bind)到一个选择:

var bars = vis.selectAll("rect.bar")
.data(data)

enter 集现在包含所有这些数据。如果我现在更改数据:

var data = [
{label:'a', value:99},
{label:'c', value:2}
{label:'b', value:3},
]

D3 如何判断哪些值是更新的、移动的还是新的?它是根据对象身份完成的吗?有没有办法让它使用标签字段来填充输入集?

最佳答案

如果我没有正确理解你的问题,你想知道 D3 如何将给定对象与给定 DOM 元素相关联。

默认情况下,如果您没有设置键函数(更多内容见下文),对象将按顺序关联。根据 API:

...the first datum in data is assigned to the first selected element, the second datum to the second selected element, and so on.

让我们在下面的例子中看到这一点。第一个数组是这样的:

var data = [{
label: 'a',
value: 1
}, {
label: 'b',
value: 3
}, {
label: 'c',
value: 2
}];

第二个数组也有 3 个对象。但要注意变化:第一个是标签c,第三个是标签a。它们被交换:

var data2 = [{
label: 'c',
value: 99
}, {
label: 'b',
value: 2
}, {
label: 'a',
value: 3
}];

因此,第一个数据中相对于 a 的柱将在第二个数据中获得 c 的值。查看演示,点击按钮:

var svg = d3.select("svg");

var data = [{
label: 'a',
value: 1
}, {
label: 'b',
value: 3
}, {
label: 'c',
value: 2
}];

var data2 = [{
label: 'c',
value: 99
}, {
label: 'b',
value: 2
}, {
label: 'a',
value: 3
}];

var xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, 260]);

var yScale = d3.scaleBand()
.domain(data.map(d => d.label))
.range([10, 140])
.padding(0.3);

var rects = svg.selectAll("foo")
.data(data)
.enter()
.append("rect");

rects.attr("x", 40)
.attr("y", d => yScale(d.label))
.attr("height", yScale.bandwidth)
.attr("width", d => xScale(d.value))
.attr("fill", "teal");

d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(40,0)"))

d3.select("button").on("click", function() {

xScale.domain([0, d3.max(data2, d => d.value)]);

rects.data(data2);

rects.transition()
.duration(1000)
.attr("width", d => xScale(d.value))

})
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Click</button>
<br>
<svg></svg>

如你所见,点击按钮后的图表显然是不正确的。

为避免这种情况,确保先前绑定(bind)到标签 a 的 DOM 元素在数据数组更改时仍将绑定(bind)到该标签 a,我们必须使用关键功能:

A key function may be specified to control which datum is assigned to which element, replacing the default join-by-index. This key function is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). The key function is then also evaluated for each new datum in data, being passed the current datum (d), the current index (i), and the group’s new data, with this as the group’s parent DOM element. The datum for a given key is assigned to the element with the matching key. If multiple elements have the same key, the duplicate elements are put into the exit selection; if multiple data have the same key, the duplicate data are put into the enter selection.

在您的情况下,这将是关键功能:

.data(data, d => d.label)
//key-------^

检查完全相同的代码,但有一个键函数:

var svg = d3.select("svg");

var data = [{
label: 'a',
value: 1
}, {
label: 'b',
value: 3
}, {
label: 'c',
value: 2
}];

var data2 = [{
label: 'c',
value: 99
}, {
label: 'b',
value: 2
}, {
label: 'a',
value: 3
}];

var xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, 260]);

var yScale = d3.scaleBand()
.domain(data.map(d => d.label))
.range([10, 140])
.padding(0.3);

var rects = svg.selectAll("foo")
.data(data, d => d.label)
.enter()
.append("rect");

rects.attr("x", 40)
.attr("y", d => yScale(d.label))
.attr("height", yScale.bandwidth)
.attr("width", d => xScale(d.value))
.attr("fill", "teal");

d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(40,0)"))

d3.select("button").on("click", function() {

xScale.domain([0, d3.max(data2, d => d.value)]);

rects.data(data2, d => d.label);

rects.transition()
.duration(1000)
.attr("width", d => xScale(d.value))

})
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Click</button>
<br>
<svg></svg>

您可以看到,尽管对象的顺序在新数据数组中有所不同(c 是第三个,现在是 c 是第一个),这无关紧要,因为 D3 将数据绑定(bind)到每个 DOM 元素,同时考虑到 label 属性。

关于d3.js - D3 变化检测是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43890277/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com