更改存储在数组中的许多节点的冲突行为 [英] Change the collision behavior of many nodes stored in an array

查看:151
本文介绍了更改存储在数组中的许多节点的冲突行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

when using the force layout in d3.js it is possible to push nodes away with the help of the collision force by increasing an imaginary radius that surrounds the nodes.

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

I created a seperate button named button and i want to use .data() (to select a whole array) to increase the collide radius into 40 of many nodes when click on that button. For example when a filtered number of nodes is stored in an array called abc, i tried this code:

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()的帮助,它返回两个节点之间的最短路径。

但不幸的是它不工作。也许有人可以帮助我的问题。推送节点的基本概念已在此处讨论:使用力分布式元素的布局物理
非常感谢!

I am able to click on 2 nodes and store these 2 nodes and all the nodes between them in the arrayabc. This is possible with the help of the d3.js function path()which returns the shortest way between 2 nodes.
But unfortunally it does not work. Maybe there is someone who can help me with the problem. The basic idea of pushing nodes away is already discussed in here: Using the force-layout physics for seperated elements Thanks so much!

推荐答案

如何过滤节点选择的想法。

After several comments I finally have an idea of how you are filtering the node selection.

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

In the following demo, the circles have 4 different colours:

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

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

因此,当您单击按钮时,我们只需用红色 r 属性,使碰撞半径增加,使用每个

So, when you click the button, we simply filter the nodes with "red" colour and increase their r property, making the collide radius increase, using each:

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

如果您要使用 data ,你可以使用 forEach

If you want use data as a getter, you can do it with a forEach:

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

其结果相同。

这里是一个演示,所有红色节点将点击后推开其他节点,冲突半径为40:

Here is a demo, all red nodes will push away the other nodes after the click, with a collide radius of 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>

这篇关于更改存储在数组中的许多节点的冲突行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆