我正在尝试使用 d3.js 创建排序算法的可视化。为此,我想创建几个具有不同半径的圆,然后在排序算法工作时将它们一一交换。尝试这样做时,我遇到了以下问题:当我更新与 d3 选择关联的数据,然后尝试使用 .data()
取回它时,我得到了未更改的数据(因为我没有更新它)。仅当我使用 key
函数跟踪对象时才会出现此问题。
代码如下。如果单击“检查”,您会在控制台中看到 [1, 3, 2]
,这是正确的初始状态。如果然后单击“do”,将调用update
函数,并且圆圈将根据新数据更改其位置。但是,如果您再次单击“检查”,您仍然会得到 [1, 3, 2]
而不是预期的 [3, 2, 1]
。
那么,有两个问题:
- 为什么会有这样的行为?
- 如何克服这个问题,即从选择中获取更新的数据?
function key(d) {
return d
}
function update(data) {
return d3.select("#picture")
.selectAll("circle")
.data(data, key)
.transition()
.attr("cx", function(d, i) {return (i+1)*50;});
}
$(function() {
d3.select("#picture")
.selectAll("circle")
.data([1, 3, 2], key)
.enter()
.append("circle")
.attr("cx", function(d, i) {return (i+1)*50;})
.attr("cy", 100)
.attr("r", function(d) {return (d+1)*10;})
.style("fill", "none")
.style("stroke", "steelblue");
$("#do_it").click(function() {
update([3, 2, 1]);
});
$("#check").click(function() {
console.log(d3.select("#picture")
.selectAll("circle").data());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="check">check</button>
<button id="do_it">do</button><br/>
<svg id="picture" width=300 height=150></svg>
最佳答案
数据的顺序不会完全发生变化,因为您使用了 key 。如果您没有使用 key ,顺序就会改变。
圆圈是通过以下关系创建的:
- 圆
0
以1
作为基准 - 圆
1
以3
作为基准 - 圆
2
以2
作为基准。
每个数据都用作一个键来识别圆。当您更新数据时,这种关系也不会改变,因为您已经设置了 key 。
当您在更新(“执行”)功能后对数据进行 console.log 时,您不会获得有关圆的新位置的数据。事实上,当您在更新后 console.log 数据时,您会得到相同的结果:
- 圆
0
以1
作为基准 - 圆
1
以3
作为基准 - 圆
2
以2
作为基准。
这些不是圆圈的位置,而是它们创建的顺序。
但是,如果您将 console.log 放入 update
函数中,您可以看到位置正在发生变化:
console.log("circle at position " + i + ", data: " + d)
查看演示,单击“do”并查看与不同位置的圆圈关联的数据:
function key(d) {
return d
}
function update(data) {
return d3.select("#picture")
.selectAll("circle")
.data(data, key)
.transition()
.attr("cx", function(d, i) {
console.log("circle at position " + i + ", data: " + d)
return (i+1)*50;});
}
$(function() {
d3.select("#picture")
.selectAll("circle")
.data([1, 3, 2], key)
.enter()
.append("circle")
.attr("cx", function(d, i) {return (i+1)*50;})
.attr("cy", 100)
.attr("r", function(d) {return (d+1)*10;})
.style("fill", "none")
.style("stroke", "steelblue");
$("#do_it").click(function() {
update([3, 2, 1]);
});
$("#check").click(function() {
console.log(d3.select("#picture")
.selectAll("circle").data());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="check">check</button>
<button id="do_it">do</button><br/>
<svg id="picture" width=300 height=150></svg>
关于javascript - 使用 key 时无法获取 d3 选择的更新数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42419205/