我有一个带有forceCollide的气泡图。我正在尝试更新数据并在调用功能时更改圆的半径(不带按钮) 此代码正常工作。但是当我使用新数据重新计算功能时,它会重新绘制旧圈子。
function DrawBubbleChart(data) {
var svg = d3.select("svg")
...
var node = svg.selectAll(".circles")
...
var simulation = d3.forceSimulation(data)
.force("x", ...)
.force("y", ...)
.force("collide", ...);
simulation.nodes(data)
.on("tick", ...);
d3.select("#btn").on("click", () => {
node.transition().duration(1000).attr("r", d => d.r);
simulation.nodes(data);
simulation.alpha(0.8).restart();
})
}
我正在尝试:
function DrawBubbleChart(data) {
if(empty){
var svg = d3.select("svg")
...
var node = svg.selectAll(".circles")
...
var simulation = d3.forceSimulation(data)
.force("x", ...)
.force("y", ...)
.force("collide", ...);
simulation.nodes(data)
.on("tick", ...);
} else {
//d3.select("#btn").on("click", () => {
node.transition().duration(1000).attr("r", d => d.r);
simulation.nodes(data);
simulation.alpha(0.8).restart();
})
}
或类似的东西。这个的最佳方法(解决方案)是什么?
答案 0 :(得分:1)
创建单个函数来绘制和更新气泡图表并不是一个好主意,原因很简单:更新图表时,您必须创建一个具有访问权限的函数到泡沫的先前位置和大小。这些是模拟分配的属性:
而且,在您的情况下,还有一个r
。这是可能的,但它很复杂。
我的建议是:创建第一次绘制气泡的函数,然后在该函数内创建另一个处理新数据的函数。这样,过渡是顺利的。
例如,在下面的演示中,我检查气泡数据并更改r
属性。您可以创建一个类似的函数,用于更新绑定到气泡的数据,保持其位置。
以下是演示:
var svg = d3.select("svg");
var colour = d3.scaleOrdinal(d3.schemeCategory10);
var data = d3.range(30).map(d => ({
r: 6
}));
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(150).strength(0.05))
.force("y", d3.forceY(75).strength(0.05))
.force("collide", d3.forceCollide(function(d) {
return d.r + 1;
}));
var node = svg.selectAll(".circles")
.data(data)
.enter()
.append("circle")
.attr("r", d => d.r)
.attr("fill", (d, i) => colour(i));
setInterval(()=>{
d3.selectAll("circle").data().forEach(d => d.r = Math.random()*15);
node.transition().duration(400).attr("r", d => d.r);
simulation.nodes(data);
simulation.alpha(0.8).restart();
}, 3000);
simulation.nodes(data)
.on("tick", d => {
node.attr("cx", d => d.x).attr("cy", d => d.y);
});

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;