实时添加节点时,D3动态网络变慢 [英] D3 dynamic network slow when adding nodes realtime

查看:69
本文介绍了实时添加节点时,D3动态网络变慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力弄清为什么在流式处理节点和流时,我的 codepen 变慢的原因实时链接.

I am struggling to work out why my codepen is slow when I stream the nodes and links real-time.

在Codepen中,我通过具有links1nodes1数组来模拟了实时内容. 我正在使用forEach添加节点和链接,并分别调用add_prcadd_conn,它们在内部调用refresh来显示新添加的节点或链接.

In the codepen, I have simulated the real-time stuff by having links1 and nodes1 array. I am adding the nodes and links using forEach and calling add_prc and add_conn respectively which internally calls the refresh to display the newly added node or link.

请点击reset按钮开始仿真.

推荐答案

为解决重大问题而进行的较小更改.

Minor change to fix a major issue.

这是一个截图,可以清楚地说明添加节点,链接的速度(这只是通过最初的重置单击,想象一下当节点数增加时实时添加的节点数):

Here's a screenshot which will clearly explain the slowdown of adding the nodes,links (and this was just by the initial reset click, IMAGINE the number of nodes it'd add in real time when the number of nodes would increase):

要解决此问题,您必须更改节点输入选择(现在不正确).这是新节点的输入选择:

To fix this, you'll have to change the node enter selection (which is incorrect now). Here's the new node enter selection:

node = node.data(nodes);

var nodeEnter = node.enter().insert("g").attr("class", "node")
   .call(force.drag);

nodeEnter
 .append("image")
 ...

nodeEnter
 .append('text')
 ...

请注意不同之处,我不会在每次通话时都添加imagetext.

Note the difference, I'm not appending image and text on every call.

这是代码段:

#nodeConsole {
  width: 80%;
  height: 1px;
  font-family: courier new;
  padding: 1px;
  border: 3px solid gray;
  margin-top: 1px;
  overflow: auto;
}

#linkedNodes {
  width: 80%;
  font-family: courier new;
  padding: 10px;
}

#srcNodes {
  width: 40%;
  font-family: courier new;
  padding: 8px;
}

#targetNodes {
  width: 40%;
  font-family: courier new;
  padding: 8px;
}

rect {
  fill: none;
  pointer-events: all;
}

.node {
  fill: #000;
}

.cursor {
  fill: none;
  stroke: brown;
  pointer-events: none;
}

.link {
  stroke: #999;
}
.node text {
  pointer-events: none;
  font: 10px sans-serif;
}

path.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

    <script src="https://d3js.org/d3.v3.min.js"></script>
    <button id="ref" onclick="refresh()">refresh </button>
    <button id="reset" onclick="reset()">reset </button>
    <script>
    
    

 var links1 = [{"source":"ctfa","target":"tfa"},
 {"source":"cea","target":"tea"},
 {"source":"ctfe","target":"tfe"},
 {"source":"ctee","target":"tee"},
 {"source":"ctfu","target":"tfu"},
 {"source":"cteu","target":"teu"},
 {"source":"rfa","target":"tfa"},
 {"source":"rea","target":"tea"},
 {"source":"rfe","target":"tfe"},
 {"source":"ree","target":"tee"},
 {"source":"rfu","target":"tfu"},
 {"source":"reu","target":"teu"},
 {"source":"r1fa","target":"rfa"},
 {"source":"r1fa","target":"gfa"},
 {"source":"r1fa","target":"ggf"},
 {"source":"r1ea","target":"rea"},
 {"source":"r1ea","target":"gea"},
 {"source":"r1ea","target":"gge"},
 {"source":"r1fe","target":"rfe"},
 {"source":"r1fe","target":"gfe"},
 {"source":"r1fe","target":"ggf"},
 {"source":"r1ee","target":"ree"},
 {"source":"r1ee","target":"gee"},
 {"source":"r1ee","target":"gge"},
 {"source":"r1fu","target":"rfu"},
 {"source":"r1fu","target":"gfu"},
 {"source":"r1fu","target":"ggf"},
 {"source":"r1eu","target":"reu"},
 {"source":"r1eu","target":"geu"},
 {"source":"r1eu","target":"gge"},
 {"source":"hh1fa","target":"ggf"},
 {"source":"hh1ea","target":"gge"},
 {"source":"hh1fe","target":"ggf"},
 {"source":"hh1ee","target":"gge"},
 {"source":"hh1fu","target":"ggf"},
 {"source":"hh1eu","target":"gge"},
 {"source":"dbfa","target":"gfa"},
 {"source":"dbea","target":"gea"},
 {"source":"dbfe","target":"gfe"},
 {"source":"dbee","target":"gee"},
 {"source":"dbfu","target":"gfu"},
 {"source":"dbeu","target":"geu"},
 {"source":"hflse","target":"tee"},
 {"source":"hfnyse","target":"teu"},
 {"source":"hfnse","target":"teu"},
 {"source":"hfret","target":"tfu"},
 {"source":"hfebs","target":"tfe"},
 {"source":"hfint","target":"tfu"},
 {"source":"c1e","target":"ctee"},
 {"source":"c1e","target":"gge"},
 {"source":"c2e","target":"ctee"},
 {"source":"c3e","target":"cteu"},
 {"source":"c4e","target":"cteu"},
 {"source":"c5e","target":"ggf"},
 {"source":"d1e","target":"ctee"},
 {"source":"c1f","target":"ctfe"},
 {"source":"c2f","target":"ctfe"},
 {"source":"c3f","target":"ggf"},
 {"source":"c4f","target":"gge"},
 {"source":"c5f","target":"ctfa"},
 {"source":"d1f","target":"ctfe"}];

var nodes1 = [{"id":"tfa"},
 {"id":"tea"},
 {"id":"tfe"},
 {"id":"tee"},
 {"id":"tfu"},
 {"id":"teu"},
 {"id":"ctfa"},
 {"id":"cea"},
 {"id":"ctfe"},
 {"id":"ctee"},
 {"id":"ctfu"},
 {"id":"cteu"},
 {"id":"rfa"},
 {"id":"rea"},
 {"id":"rfe"},
 {"id":"ree"},
 {"id":"rfu"},
 {"id":"reu"},
 {"id":"r1fa"},
 {"id":"r1ea"},
 {"id":"r1fe"},
 {"id":"r1ee"},
 {"id":"r1fu"},
 {"id":"r1eu"},
 {"id":"hh1fa"},
 {"id":"hh1ea"},
 {"id":"hh1fe"},
 {"id":"hh1ee"},
 {"id":"hh1fu"},
 {"id":"hh1eu"},
 {"id":"dbfa"},
 {"id":"dbea"},
 {"id":"dbfe"},
 {"id":"dbee"},
 {"id":"dbfu"},
 {"id":"dbeu"},
 {"id":"gfa"},
 {"id":"gea"},
 {"id":"gfe"},
 {"id":"gee"},
 {"id":"gfu"},
 {"id":"geu"},
 {"id":"gge"},
 {"id":"ggf"},
 {"id":"hflse"},
 {"id":"hfnyse"},
 {"id":"hfnse"},
 {"id":"hfret"},
 {"id":"hfebs"},
 {"id":"hfint"},
 {"id":"c1e"},
 {"id":"c2e"},
 {"id":"c3e"},
 {"id":"c4e"},
 {"id":"c5e"},
 {"id":"d1e"},
 {"id":"c1f"},
 {"id":"c2f"},
 {"id":"c3f"},
 {"id":"c4f"},
 {"id":"c5f"},
 {"id":"d1f"}];
    //refresh();
    
     function reset() {
        nodes1.forEach(function(d){ add_prc(d)  });
        links1.forEach(function(d){ add_con(d)  });
    }
 
    function add_prc(newNode) {
        //console.log(newNode);
        addNodeCanvas(newNode.id,newNode.grp);
    }

    function add_con(newConnection) {
        //console.log(newConnection);
        addLinkCanvas( newConnection.source,newConnection.target);  
    }

    //setInterval(refresh, 15000);

    function addNodeCanvas(nodeName,g) {
        var node = {        x: 900,    y: 900,        id: nodeName,    grp:g  };
        var n = nodes.push(node);
       // console.log(node);
        refresh();
    }
    
    function addLinkCanvas(idSrc, idTarget) {
        if (idSrc != idTarget) {
            var s = {},        t = {};
            nodes.forEach(function(curNode) {
                if (typeof curNode.id != "undefined") {
                    if (curNode.id == idSrc) {          s = curNode;        }
                    if (curNode.id == idTarget) {          t = curNode;        }
                }
            });

            //console.log( { s,t});
            links.push({     source: s,      target: t    });
        };
        refresh();
    }

  var width = 960,
  height = 500;

var fill = d3.scale.category20();

var links = [{ source:  "FH", target: "TP" }];
var nodes = [
    { id: "FH", x: 100, y: 110 },
    { id: "TP", x: 200, y: 110 },
    { id: "GW", x: 200, y: 110 },
    { id: "DB", x: 100, y: 110 }
  ]

var map = {}
nodes.forEach(function(d,i){
  map[d.id] = i;
})

links.forEach(function(d) {
  d.source = map[d.source];
  d.target = map[d.target];
})

var force = d3.layout
  .force()
  .size([width, height])
  .nodes(nodes) .links(links)
  .linkDistance(50)
  .charge(-50)
  .on("tick", tick);

var svg = d3
  .select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

// build the arrow.
var arrows = svg
  .append("svg:defs")
  .selectAll("marker")
  .data(["arrow"]) // Different link/path types can be defined here
  .enter()
  .append("svg:marker") // This section adds in the arrows
  .attr("id", String)
  .attr("viewBox", "0 -5 10 10")
  .attr("refX", 15)
  .attr("refY", -1.5)
  .attr("markerWidth", 6)
  .attr("markerHeight", 6)
  .attr("orient", "auto")
  .append("svg:path")
  .attr("d", "M0,-5L10,0L0,5");


svg
  .append("rect")
  .attr("width", width)
  .attr("height", height);

var nodes = force.nodes(),
  links = force.links(),
  node = svg.selectAll(".node"),
  link = svg.selectAll(".link");


function tick() {
  link.attr("x1", function(d) {
      return d.source.x;
    })
    .attr("y1", function(d) {
      return d.source.y;
    })
    .attr("x2", function(d) {
      return d.target.x;
    })
    .attr("y2", function(d) {
      return d.target.y;
    });

  node.attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  });
}


 function refresh(){
  
  node = node.data(nodes);
  
  var nodeEnter = node.enter().insert("g")
  	.attr("class", "node")
    .call(force.drag);
  
  nodeEnter
    .append("image")
    .attr("xlink:href", "https://github.com/favicon.ico")
    .attr("x", -8)
    .attr("y", -8)
    .attr("width", 16)
    .attr("height", 16);
  nodeEnter
    .append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(function(d) {
      return d.id;
    });
  node.exit().remove();

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

  force.start();
}


    </script>

这是 JSFIDDLE (我是jsfiddle迷).

And here's a JSFIDDLE (I'm a jsfiddle fan).

我看到您从画布移到了SVG.无论如何,希望这会有所帮助.

And I see that you moved from a canvas to SVG. Anyway, hope this helps.

这篇关于实时添加节点时,D3动态网络变慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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