【问题标题】:Filter out nodes and turn them inactive过滤掉节点并使其处于非活动状态
【发布时间】:2017-06-23 23:23:58
【问题描述】:

我正在使用 d3.js 和 force-layout。现在,根据这个问题的答案: 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>

【问题讨论】:

    标签: javascript d3.js nodes force-layout


    【解决方案1】:

    这样做的一种方法是检查它是否是第一次运行模拟,如果不是,则过滤掉蓝色圆圈:

    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);
            }
        });
    

    这里是演示:

    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);
        }
      });
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <button>Click me</button>
    <br>
    <svg></svg>

    顺便说一句,你想要的结果(“绿色和黄色节点被推开,但蓝色节点保持在原来的位置”)在视觉上是不愉快的。

    【讨论】:

    • 您能否解释一下,我们需要检查模拟是否第一次运行?
    • 因为您不希望蓝色圆圈在左上角堆积。
    • 谢谢杰拉尔多。一如既往的大帮助。我刚刚打开了一个关于类似问题的新问题。有时间的话可以去看看。
    猜你喜欢
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多