我有一个带碰撞检测的气泡图,它通过滑块改变半径。 模拟定义如下:
var simulation = d3.forceSimulation()
.force("x", d3.forceX(width/2).strength(0.05))
.force("y", d3.forceY(height/2).strength(0.05))
.force("collide", d3.forceCollide(function(d){
return scaleRadius(d.value)+1;
}));
操纵滑块后,我调用一个函数,该函数又调用以下代码:
var circles = d3.selectAll(".circlesvg")
circles.selectAll(".artist").data(datapoints)
.transition()
.attr("r", function(d){
return d.value;
})
因为半径可以变大,我需要重新运行模拟来检查碰撞并让DOM正确转换。然而,模拟代码似乎没有做任何事情。
simulation.nodes(datapoints)
.on("tick", ticked)
我想知道我是否在模拟和节点之间没有正确的绑定。
提前感谢您的帮助。
答案 0 :(得分:1)
传递新数据后......
simulation.nodes(data);
......你必须重新加热模拟:
simulation.alpha(0.8).restart();
这是一个非常简化的演示:
var svg = d3.select("svg");
var colour = d3.scaleOrdinal(d3.schemeCategory10);
var data = [{r: 10},{r: 5},{r: 15},{r: 20},{r: 9},
{r: 30},{r: 12},{r: 7},{r: 26},{r: 17}];
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))
simulation.nodes(data)
.on("tick", d => {
node.attr("cx", d => d.x).attr("cy", d => d.y);
});
d3.select("button").on("click", () => {
data.forEach(d => d.r = Math.random() * 30);
node.transition().duration(500).attr("r", d => d.r);
simulation.nodes(data);
simulation.alpha(0.8).restart();
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Randomize</button>
<svg></svg>