javascript - 更改存储在数组中的许多节点的碰撞行为

标签 javascript select d3.js nodes force-layout

在 d3.js 中使用力布局时,可以通过增加围绕节点的假想半径,借助碰撞力将节点推开。

我创建了一个名为 button 的单独按钮,我想使用 .data() (选择整个数组)将碰撞半径增加到 40 个节点当点击该按钮时。例如,当过滤后的节点数存储在名为 abc 的数组中时,我尝试了以下代码:

var node =......
    .on("click", function(d, i) {

        abc = start && start.path(d) || [];

        node.style("fill", function(n) {
            if (n == start ) {             
               return "yellow";
            } else if ( n == d) {
               return "green"
            } else if (abc.includes(n)) {
               return "red"
            } else {
               return "lightgrey"
            }
         .....
      }});

button.on("click", function(d) {
   d3.selectAll("circle").data().forEach(d => d.r = 6);
   d3.select(abc).data().r = 40;
   simulation.nodes(data);
   simulation.alpha(0.8).restart();
})

我可以单击 2 个节点并将这 2 个节点以及它们之间的所有节点存储在数组abc 中。这可以在 d3.js 函数 path() 的帮助下实现,该函数返回 2 个节点之间的最短路径。
但不幸的是它不起作用。也许有人可以帮助我解决这个问题。推开节点的基本思想已经在这里讨论过:Using the force-layout physics for seperated elements 非常感谢!

最佳答案

经过几次评论后,我终于了解了如何过滤节点选择。

在下面的演示中,圆圈有 4 种不同的颜色:

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

node.attr("fill", (d, i) => colours[i%4]);

因此,当您单击按钮时,我们只需过滤具有“红色”颜色的节点并增加其 r 属性,从而使用 each 增加碰撞半径:

node.filter(function() {
    return d3.select(this).attr("fill") === "red"
}).each(d => d.r = 40);

如果您想使用 data 作为 getter,您可以使用 forEach 来实现:

node.filter(function() {
    return d3.select(this).attr("fill") === "red"
}).data().forEach(d => d.r = 40);

结果相同。

这里是一个演示,点击后所有红色节点都会推开其他节点,碰撞半径为40:

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 - 更改存储在数组中的许多节点的碰撞行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42404896/

相关文章:

javascript - HTTP 请求负载中未定义的参数属性将被清除

sql - sql语法有什么问题

mysql order by with union 似乎不起作用

javascript - 从 d3 中的系列创建系列

javascript - 添加滚动条以查看 SVG d3.js 的全部内容

javascript - 在 Canvas 中绘制多条贝塞尔曲线路径

javascript - Angular : Filter object data to build a Highchart Widget with distinct elements attributes

javascript - 随机播放 div 但显示的数量有限

MySQL 选择最大日期和最大时间的位置

javascript - 如何在 d3js 中创建具有重复字符串值的 x 轴?