【问题标题】:Delete connection/ circle in a network diagram using d3.js使用 d3.js 删除网络图中的连接/圆圈
【发布时间】:2014-09-17 06:29:26
【问题描述】:

请查看我的jsFiddle,它关联了以下数据:

rules = [['L5', 'L2'], ['L5', 'L2'], ['L4', 'L2'], ['L2', 'L1'], ['L3', 'L1'], ['L1', 'C1'],  ['C1', 'R2'], ['C1', 'R3'], ['R2', 'R4'], ['R3', 'R6'], ['R3', 'R7']];

,我的目标是有一个按钮,我可以用它来删除图表中的一个圆圈。例如,当我按下 e 按钮时,我删除了 R3、R2、L5。完成后,我需要在以下之间建立新的联系: 如果 R3 被删除,那么 R7 和 R6 应该指向 C1 如果 R2 被删除,那么 R5 应该连接到 C1 如果是 L5,则不应创建新连接。

如果您有任何意见或建议或想法 - 将是完美的。当然,我总是可以遍历源并删除不需要的圈子并创建新的连接,但我正在寻找比这更有效的方法+我也有和撤消按钮,它可以恢复所做的任何更改,但一次一个问题。

谢谢!

【问题讨论】:

    标签: networking d3.js geometry diagram


    【解决方案1】:

    这称为网络投影,您不应将其视为删除节点,而应将其视为将节点转换为边。从 D3 的角度来看,这并不是说您对任务的看法是错误的——您需要删除并创建新节点,但使用正确的术语会引导您找到其他示例。当您使用一种类型的网络节点(例如论文)并将它们用作连接另一种类型(例如人)的节点以将人的网络和他们写的论文转换为连接到的人的网络时,就会发生多模式网络投影和他们一起写论文的人。

    要使用 D3 完成此任务,您必须做一些事情。

    首先,您需要为链接和边设置唯一的 ID,并在绑定数据时使用它们。当您想使用 D3 进行复杂的元素更新和删除时,这通常是必要的:

     d3.selectAll(".link")
     .data(links, function (d) {return d.id})
    
     d3.selectAll(".node")
     .data(nodes, function (d) {return d.id})
    

    在您的情况下,这些唯一 id 可以是节点的节点名称和链接的连接节点的连接节点名称。

    有了这个,你可以构建一个简单的函数,当你点击一个节点时会触发这个函数:

     function collapseNode(d,i) {
       force.stop();
    
       removedLinks = links.filter(function (p) {return p.source == d.id || p.target == d.id});
       filteredLinks = links.filter(function (p) {return p.source != d.id && p.target != d.id});
    
       filteredNodes = nodes.filter(function (p) {return p.id != d.id});
    
       //create new links
       //this will have problems with parallel edges
       for (x in removedLinks) {
         for (y in removedLinks) {
           if (removedLinks[x].source != d && removedLinks[y].source != d) {
             filteredLinks.push({source: removedLinks[x].source, target: removedLinks[y].source,
               id: generateAnID})
           }
           else if (removedLinks[x].target != d && removedLinks[y].source != d) {
             filteredLinks.push({source: removedLinks[x].target, target: removedLinks[y].source,
               id: generateAnID})
           }
           else if (removedLinks[x].source != d && removedLinks[y].target != d) {
             filteredLinks.push({source: removedLinks[x].source, target: removedLinks[y].target,
               id: generateAnID})
           }
           else if (removedLinks[x].target != d && removedLinks[y].target != d) {
             filteredLinks.push({source: removedLinks[x].target, target: removedLinks[y].target,
               id: generateAnID})
           }
         }
       }
       d3.selectAll(".node").data(filteredNodes, function(d) {return d.id})
       .exit()
       .remove();
    
       d3.selectAll(".link").data(filteredLinks, function(d) {return d.id})
       .exit()
       .remove();
    
       d3.selectAll(".link").data(filteredLinks, function(d) {return d.id})
       .enter()
       .append("line)
       .attr("class", "line")
    
       force.start();
    
     } 
    

    【讨论】:

    • 这是一本非常好的读物。我对答案的第一部分比代码部分更感兴趣 :) 非常感谢,我会玷污试一试,然后告诉你它是怎么回事
    • 首先感谢您的回答,我试了一下。我确保我所有的圈子和连接的留置权现在都有 ID。然后我进入了功能。您能否详细说明一下它是如何工作的?例如,你作为这个函数的参数传入了什么?如果它不是一个大问题,也许您可​​以编辑现有的 jsfiddle.net/yeQS2/103 ,我已经对其进行了更新,因此所有元素现在都有一个 Id。感谢您的帮助
    • 能否请您稍有时间就您的回答发表更多评论
    猜你喜欢
    • 2018-03-05
    • 2020-10-20
    • 2012-11-13
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 2020-10-09
    • 1970-01-01
    相关资源
    最近更新 更多