在D3js中添加和删除节点力图 [英] Adding and Removing Nodes in D3js Force Graph

查看:1659
本文介绍了在D3js中添加和删除节点力图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从数据库加载 json 并创建一个 json 文件加载正常。现在我不知道在强制定向图中使节点响应的步骤。我需要删除并添加新节点及其链接。

  force.nodes(json.nodes)
.links (json.links)
.start();

initNodes(json);

如何使此更动态或更新而不重置整个可视化?



我已经看过这个问题几次没有回答,所以我希望有人可以发布和指导。



假设您要为节点使用< g>

  //选择要创建强制布局的元素
var el = d3.select(#svg );

//这不应该选择任何东西
el.selectAll(g)

//因为它正在与force.nodes()中的数据进行比较,
.data(force.nodes())

//调用`.enter()`返回
之间节点的差异//当前选择和force.nodes ()。此时,在选择中有
//没有节点,所以`.enter()`应该返回
// force.nodes()中的所有节点
.enter )

//创建节点
.append(g)
.attr(id,d.name)
.classed(manipulateYourNewNode ,true);

现在让我们来创建一个图形初始化后添加一个节点到布局的函数! / p>

newNodeData 是一个包含要用于新节点的数据的对象。
connectToMe 是一个字符串,包含您要连接新节点的节点的唯一ID。

  function createNode(newNodeData,connectToMe){
force.nodes()。push(newNodeData);
el.selectAll(g)
.data(force.nodes(),function(datum,index){return index})

.data()中作为可选的第二个参数给出的函数对于选择中的每个节点运行一次并再次对 force.nodes()中的每个节点,根据返回的值进行匹配。如果没有提供函数,则调用一个回退函数,返回 index (如上所述)。



但是,新选择的索引(我相信订单是随机的)和中的订单之间很可能会有争议, force.nodes()



这次, .enter()

code>只会返回您尝试添加为 newData 的节点,因为的第二个参数未找到任何键。 data()

  .enter()
.insert(g, #svg)
.attr(id,d.name)
.classed(manipulatYourNewNode,true);

createLink(connectToMe,newNodeData.name);

force.start();
}

函数createLink(下面定义)



此外, d3js API说明更新布局后应调用force.start()



注意:调用 force.stop()在我的函数的开始是一个巨大的帮助,当我第一次试图找出如何添加节点和链接到我的图。

  function createLink(from,to){
var source = d3.select(g#+ from)。 datum(),
target = d3.select(g#+ to).datum(),
newLink = {
source:source,
target:target,
value:1
};
force.links()。push(newLink);

以下代码在假设条件下工作:


  1. #links 是包含所有链接元素的包装元素

  2. 您的链接表示为< line> 元素:

      d3。 select(#links)
    .selectAll(line)
    .data(force.links())
    .enter()
    .append ;



I am loading json from database and creating a json file which loads fine. Now I don't know which steps to take for making the nodes responsive in a Force-Directed Graph. I need to remove and add new nodes and their links.

force.nodes(json.nodes)
    .links(json.links)
    .start();

initNodes(json);

How can I make this more dynamic or update it without resetting the whole visualization?

I have seen this question a couple of times not being answered so I hope someone can post and give a guide.

解决方案

Adding nodes/links to my D3 force graph was very confusing until I better understood the way I was adding the initial set of nodes.

Assuming a <g> is what you'd like to use for your nodes:

// Select the element where you'd like to create the force layout
var el = d3.select("#svg");

// This should not select anything
el.selectAll("g")

// Because it's being compared to the data in force.nodes() 
    .data(force.nodes())

// Calling `.enter()` below returns the difference in nodes between 
// the current selection and force.nodes(). At this point, there are
// no nodes in the selection, so `.enter()` should return 
// all of the nodes in force.nodes()
    .enter()

// Create the nodes
    .append("g")
    .attr("id", d.name)
    .classed("manipulateYourNewNode", true);

Now let's make that function that will add a node to the layout once the graph has been initialized!

newNodeData is an object with the data you'd like to use for your new node. connectToMe is a string containing the unique id of a node you'd like to connect your new node to.

function createNode (newNodeData, connectToMe) {
    force.nodes().push(newNodeData);
    el.selectAll("g")
       .data(force.nodes(), function(datum, index) { return index })

The function given as the optional second argument in .data() is run once for each node in the selection and again for each node in force.nodes(), matching them up based on the returned value. If no function is supplied, a fallback function is invoked, which returns the index (as above).

However, there's most likely going to be a dispute between the index of your new selection (I believe the order is random) and the order in force.nodes(). Instead you'll most likely need the function to return a property that is unique to each node.

This time, .enter() will only return the node you're trying to add as newData because no key was found for it by the second argument of .data().

       .enter()
       .insert("g", "#svg")
       .attr("id", d.name)
       .classed("manipulatYourNewNode", true);

    createLink(connectToMe, newNodeData.name);

    force.start();
}

The function createLink (defined below) creates a link between your new node and your node of choice.

Additionally, the d3js API states that force.start() should be called after updating the layout.

Note: Calling force.stop() at the very beginning of my function was a huge help for me when I was first trying to figure out how to add nodes and links to my graph.

function createLink (from, to) {
    var source = d3.select( "g#" + from ).datum(),
        target = d3.select( "g#" + to ).datum(),
        newLink = {
            source: source,
            target: target,
            value: 1
        };
    force.links().push(newLink);

The code below works under the assumptions that:

  1. #links is the wrapper element that contains all of your link elements
  2. Your links are represented as <line> elements:

    d3.select("#links")
        .selectAll("line")
        .data(force.links())
        .enter()
        .append("line");
    

这篇关于在D3js中添加和删除节点力图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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