滑块事件后D3模拟无效

时间:2017-01-11 23:32:34

标签: javascript d3.js

我有一个带碰撞检测的气泡图,它通过滑块改变半径。 模拟定义如下:

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)

我想知道我是否在模拟和节点之间没有正确的绑定。

提前感谢您的帮助。

1 个答案:

答案 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>