在 D3js 强制图中添加和删除节点

Adding and Removing Nodes in D3js Force Graph

本文关键字:添加 删除 节点 D3js      更新时间:2024-01-14

我正在从数据库加载json并创建一个加载良好的json文件。现在我不知道要采取哪些步骤来使节点在力导向图中响应。我需要删除并添加新节点及其链接。

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

如何在不重置整个可视化效果的情况下使其更加动态或更新它?

我已经看到这个问题几次没有得到回答,所以我希望有人可以发布并提供指导。

在 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()中的每个节点运行一次,根据返回值匹配它们。如果未提供任何函数,则调用回退函数,该函数返回index(如上所述(。

但是,您新选择的索引(我相信顺序是随机的(和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");
    

您可以在此处查看如何附加新节点和关系的示例:http://bl.ocks.org/2432083

摆脱节点和关系稍微棘手一些,但您可以在此处看到该过程:http://bl.ocks.org/1095795