我已将大部分d3代码重写为v4,但新的更新模式让我失望。以下示例用于力图。每次更新时,在第一个容器中创建一个重复的圆圈。我的示例中的数据实际上并没有改变,但它无关紧要。如果我使用新数据,则会出现相同的问题(重复的圆圈)。
var w = 800,
h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
var dataset = {};
function setData() {
dataset.nodes = [{
value: 200
}, {
value: 100
}, {
value: 50
}];
}
setData();
var rScale = d3.scaleSqrt()
.range([0, 100])
.domain([0, d3.max(dataset.nodes.map(function(d) {
return d.value;
}))]);
var node = svg.append("g")
.attr("class", "nodes")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")")
.selectAll(".node");
var simulation = d3.forceSimulation(dataset.nodes)
.force("charge", d3.forceManyBody().strength(-1600))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaDecay(.05)
.on("tick", ticked);
function ticked() {
node.selectAll("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
function restart() {
// Apply the general update pattern to the nodes.
node = node.data(dataset.nodes, function(d) {
return d.id;
});
node.exit().remove();
node = node.enter().append("g")
.attr("class", "node")
.merge(node);
node.append("circle")
.attr("r", function(d) {
return rScale(d.value);
});
// Update and restart the simulation.
simulation.nodes(dataset.nodes);
simulation.alpha(1).restart();
}
restart();
function update() {
setData();
restart();
}
d3.select("#update").on("click", update);
如果单击此编码板中的“更新”按钮(https://codepen.io/cplindem/pen/wpQbQe),则会在模拟重新开始时看到所有三个圆圈都有效,但在最大的圆圈后面,还有另一个相同的圆圈,它没有动画效果。如果您检查它,您还可以看到新的圆圈出现在html中。 我做错了什么?
答案 0 :(得分:1)
您的第一个问题似乎是您在'id'字段上输入数据,但您的数据没有任何ID,因此需要更改或者您只是不断添加新组:
function setData() {
dataset.nodes = [{
value: 200,
id: "A"
}, {
value: 100,
id: "B"
}, {
value: 50,
id: "C"
}];
console.log("dataset", dataset);
}
第二个问题是你合并新的和更新的选择,然后将新的圈子添加到所有选择,甚至是现有的圈子(因此在按下更新时每组有多个圈子)。我通过这样做得到了它:创建新节点,与现有选择合并,只为新节点添加圆圈,更新所有节点中的圆圈:
node.exit().remove();
var newNodes = node.enter().append("g");
node = newNodes
.attr("class", "node")
.merge(node);
newNodes.append("circle");
node.select("circle")
.attr("r", function(d) {
return rScale(d.value);
});
第二位是否是最优的我不知道,我自己仍然更加坚持v3 ...