【问题标题】:Adding a node dynamically in d3 canvas在 d3 画布中动态添加节点
【发布时间】:2018-10-16 16:19:26
【问题描述】:

我是 d3 的新手。我用 JSON 节点尝试了几个例子,得到了一个很好的工作网络图。

但是,当我尝试动态添加一个额外的节点时,它并没有出现在屏幕上。

我从Force Dragging III Canvas开始,然后尝试添加以下代码,但不起作用;我该如何解决这个问题,请帮忙?

graph.addNode("NewNode");

function addNode (id) {
    nodes.push({"id":id});
    restart();

}


function restart() {
  node = node.data(nodes);

  node.enter().insert("circle", ".cursor")
      .attr("class", "node")
      .attr("r", 5);


  node.exit()
      .remove();

  link = link.data(links);

  link.enter().insert("line", ".node")
      .attr("class", "link");
  link.exit()
      .remove();

  force.start();
}

【问题讨论】:

    标签: d3.js force-layout


    【解决方案1】:

    有一些不太明显的力量在起作用:

    • 初始化后,原始数据数组中的节点获得了一堆新属性
    • 初始化后,原始数据数组中的链接将转换为新形式。

    此外,如果您遵循链接示例,则不需要进入/更新/退出样式循环 - 强制使用原始数据数组,而不是任何 DOM 元素。

    节点

    在您的参考示例中,节点仅以 id 和组开头:

    {"source": "Montparnasse", "target": "Babet", "value": 2}
    

    但是,在使用simulation.nodes(nodes) 初始化后,它们会得到一些附加参数:

    group: 1
    id: "Myriel"
    index: 0
    vx: 0.0026819653036056477
    vy: -0.0005005454729913666
    x: 306.003096668046
    y: 359.07887474183434
    

    这四个附加属性跟踪节点。每个刻度都要求这些属性已经存在,如果它们不存在,我们就会遇到问题。因此,如果我们提供一个新节点,我们可以为其赋予 x,y,vy,vx 属性,以便无缝添加(example,在所有示例中单击以添加节点)。这给出了一个简单的 addNode 函数:

      function addNode () {
        var id = graph.nodes.length;
        graph.nodes.push({"id":id, index: id, x: width/2, y: height/2, vx: 0, vy: 0});
      }
    

    或者,我们可以使用simulation.nodes() (example) 重新初始化节点,力会在为其提供所需位置的同时自动放置它。但是,除非您指定 x 和 y 坐标 (example),否则这很容易出错。

    最后一个也为我们提供了一个非常直接的 addNode 函数:

      function addNode () {
        var id = graph.nodes.length;
        graph.nodes.push({"id":id, group: 12, x: width/2, y: height/2});
        simulation.nodes(graph.nodes)
      }
    

    这应该有助于将节点添加到部队中。

    链接

    对于链接,您的参考示例中的原始数据在加载时如下所示:

    { source: "Napoleon", target: "Myriel", value: 1 }
    

    但是,在初始化链接后,采用以下形式:

    index: 0
    source: Object { id: "Napoleon", group: 1, index: 1, … } 
    target: Object { id: "Myriel", group: 1, index: 0, … }
    value: 1
    

    源和目标属性被转换为代表每个点的对象。就像节点一样,ticked 函数要求节点采用后一种形式。和上面一样,我们可以尝试复制格式,或者使用强制设置格式本身,我选择后者作为链接,同时为新节点here设置x,y。这是 addNode 函数:

      function addNode () {
        var id = graph.nodes.length;
        graph.nodes.push({"id": id, x: width/2, y: height/2});
        graph.links.push({source: "Javert", target: id });
    
      simulation
          .nodes(graph.nodes)
          .force("link")
          .links(graph.links);  
      }
    

    作为一个更复杂但理论较少的例子,这个question/answer 可能很有趣(和associated block(单击以添加/删除节点,使用左上角的按钮切换哪个操作)),其中节点添加/删除,进而影响力和 voronoi

    【讨论】:

    • 我正在接受您的“强制添加节点和链接”块,但我很好奇您如何如此顺利地添加新节点。我知道那个块是为画布设计的,但你能解释一下如何不使用画布做同样的事情吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-17
    • 2017-01-04
    • 1970-01-01
    • 2013-06-07
    • 2021-12-23
    相关资源
    最近更新 更多