在D3js力导向图中添加和删除节点

13
我从数据库中加载JSON并创建了一个能够成功加载的JSON文件。现在我不知道该采取哪些步骤让力导向图中的节点具有响应性。 我需要删除和添加新节点及其链接。
force.nodes(json.nodes)
    .links(json.links)
    .start();

initNodes(json);

如何使这个更动态化或更新它而不重新设置整个可视化呢?

我已经看到过几次这个问题没有被解答,所以我希望有人能够发布并给出指导。

2个回答

15

在我更好地理解如何添加初始节点集之前,向我的D3力导向图中添加节点/链接非常令人困惑。

假设您想要将<g>用作节点:

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

现在让我们创建一个函数,一旦图形被初始化,就会向布局添加一个节点!

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()中的每个节点运行一次,并根据返回值将它们匹配起来。如果没有提供函数,则会调用一个回退函数,该函数返回索引(如上文所述)。

然而,你新的选择集的索引(我认为顺序是随机的)和force.nodes()中的顺序很可能会产生争议。相反,你很可能需要使函数返回每个节点唯一的属性。

这一次,.enter()方法只会返回你要添加为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("line");
    

如何添加节点的回答很好,但忘了提到如何删除节点。 - Sanxofon

7

重要的部分是将.data方法返回的值保存在变量中(比如说x),并在方法结束时调用x.exit().remove()。 - Ido Ran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接