D3 Dynamic Network Slow When Adding Nodes Realtime
I am struggling to work out why my codepen is slow when I stream the nodes and links real-time. In the codepen, I have simulated the real-time stuff by having links1 and nodes1 arr
Solution 1:
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')
...
Note the difference, I'm not appending image
and text
on every call.
Here's the code snippet:
#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;
}
<scriptsrc="https://d3js.org/d3.v3.min.js"></script><buttonid="ref"onclick="refresh()">refresh </button><buttonid="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();functionreset() {
nodes1.forEach(function(d){ add_prc(d) });
links1.forEach(function(d){ add_con(d) });
}
functionadd_prc(newNode) {
//console.log(newNode);addNodeCanvas(newNode.id,newNode.grp);
}
functionadd_con(newConnection) {
//console.log(newConnection);addLinkCanvas( newConnection.source,newConnection.target);
}
//setInterval(refresh, 15000);functionaddNodeCanvas(nodeName,g) {
var node = { x: 900, y: 900, id: nodeName, grp:g };
var n = nodes.push(node);
// console.log(node);refresh();
}
functionaddLinkCanvas(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");
functiontick() {
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 + ")";
});
}
functionrefresh(){
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>
And here's a JSFIDDLE (I'm a jsfiddle fan).
And I see that you moved from a canvas to SVG. Anyway, hope this helps.
Post a Comment for "D3 Dynamic Network Slow When Adding Nodes Realtime"