过滤掉节点并将其置于非活动状态

时间:2017-06-23 23:23:59

标签: javascript d3.js nodes force-layout

我正在使用强制布局的d3.js。现在,根据这个问题的答案: Change the collision behavior of many nodes stored in an array

可以通过点击"点击我"过滤掉红色节点并推开其他节点(增加碰撞属性)。按钮。它工作得很好,但现在我希望蓝色节点不受红色节点的推离动作的影响。这意味着,绿色和黄色节点被推开,但蓝色节点保持在原始位置。所以我正在寻找一种方法来在力布局中将这些蓝色节点变为非活动状态。也许有些人可以提供帮助。谢谢你们!



var svg = d3.select("svg");

var colours = ["blue", "red", "green", "yellow"];

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) => colours[i%4]);

d3.select("button").on("click", function(d) {
		node.filter(function(){
		 return d3.select(this).attr("fill") === "red"
		}).each(d=>d.r = 40);
    simulation.nodes(data);
    simulation.alpha(0.8).restart();
})

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>
<button>Click me</button>
<br>
<svg></svg>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是检查是否是第一次运行模拟,如果不是,则过滤掉蓝色圆圈:

simulation.nodes(data)
    .on("tick", d => {
        if (firstTime) {
            node.attr("cx", d => d.x).attr("cy", d => d.y);
        } else {
            node.filter(function(e) {
                return d3.select(this).attr("fill") != "blue"
            }).attr("cx", d => d.x).attr("cy", d => d.y);
        }
    });

以下是演示:

&#13;
&#13;
var svg = d3.select("svg");

var firstTime = true;

var colours = ["blue", "red", "green", "yellow"];

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) => colours[i % 4]);

d3.select("button").on("click", function(d) {
  firstTime = false;
  node.filter(function() {
    return d3.select(this).attr("fill") === "red"
  }).each(d => d.r = 40);
  simulation.nodes(data);
  simulation.alpha(0.8).restart();
})

simulation.nodes(data)
  .on("tick", d => {
    if (firstTime) {
      node.attr("cx", d => d.x).attr("cy", d => d.y);
    } else {
      node.filter(function(e) {
        return d3.select(this).attr("fill") != "blue"
      }).attr("cx", d => d.x).attr("cy", d => d.y);
    }
  });
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Click me</button>
<br>
<svg></svg>
&#13;
&#13;
&#13;

顺便说一句,您想要的结果(&#34;绿色和黄色节点被推开,但蓝色节点保持在原始位置&#34; )在视觉上是不愉快的。