简体   繁体   中英

Dynamic Node Addition/Updation on D3 js Network Graph on button click

I'm trying to add Nodes and Links between them on a Button click without loading any .Json file.

Here is what i've done : Create Nodes/Links on document ready

 $(document).ready(function(){ var w = $("#graph").innerWidth(); var h = $("#graph").innerHeight(); var default_node_color = "#ccc"; var default_link_color = "red"; var nominal_base_node_size = 8; var nominal_text_size = 10; var max_text_size = 24; var nominal_stroke = 1.5; var highlight_stroke_width = 4; var max_stroke = 4.5; var min_zoom = 0.1; var max_zoom = 7; var svg = d3.select("#graph").append("svg"); var zoom = d3.behavior.zoom().scaleExtent([min_zoom,max_zoom]) var g = svg.append("g"); svg.style("cursor","move"); var dnodes = []; var dlinks = []; function findNode(id) { for (var i in dnodes) { if (dnodes[i]["id"] === id) return dnodes[i]; }; }; function addNode(id,name) { var newNode = findNode(id); if(newNode == undefined) { dnodes.push({"id":id,"name":name}); //update(dnodes,dlinks); } }; function addLink(sourceId, targetId) { var sourceNode = findNode(sourceId); var targetNode = findNode(targetId); if((sourceNode !== undefined) && (targetNode !== undefined)) { dlinks.push({"source": sourceNode, "target": targetNode}); //update(dnodes,dlinks); } }; addNode("1","2XYZ"); addNode("3","3XYZ"); addNode("4","4XYZ"); addNode("5","5XYZ"); addLink("1","2"); addLink("1","3"); addLink("1","4"); addLink("1","5"); var force = d3.layout.force() .linkDistance(160) .charge(-300) .friction(0.5) .size([w,h]); var nodes = force.nodes(dnodes); var links = force.links(dlinks); force.start(); //function update(dnodes, dlinks) //{ function isConnected(sourceNodeid, destNodeid) { for(var i in dlinks) { if((dlinks[i].source.id == sourceNodeid && dlinks[i].target.id==destNodeid)||((dlinks[i].source.id == destNodeid && dlinks[i].target.id==sourceNodeid))) { return true; } } if(sourceNodeid == destNodeid) { return true; } return false; }; function dragstart(d, i) { force.stop() // stops the force auto positioning before you start dragging } function dragmove(d, i) { d.px += d3.event.dx; d.py += d3.event.dy; dx += d3.event.dx; dy += d3.event.dy; tick(); } function dragend(d, i) { d.fixed = true; tick(); } var node_drag = d3.behavior.drag() .on("dragstart", dragstart) .on("drag", dragmove) .on("dragend", dragend); var link = g.selectAll(".link") .data(dlinks) .enter().append("line") .attr("class", "link") .style("stroke-width",nominal_stroke) .style("stroke", default_link_color) var node = g.selectAll(".node") .data(dnodes) .enter().append("g") .attr("class", "node") .call(node_drag); var circle = node.append("rect") .attr("x", "-15px") .attr("y", "-15px") .attr("rx", "4") .attr("ry", "4") .attr("width", "30px") .attr("height", "30px") .attr("id", function (d) {return d.id;}) .attr("fill", "#336699"); var text = g.selectAll(".text") .data(dnodes) .enter().append("text") .attr("dy", ".35em") .attr("y","22") .style("font-size", nominal_text_size + "px") text.text(function(d) { return d.name; }) .style("text-anchor", "middle"); zoom.on("zoom", function() { var stroke = nominal_stroke; if (nominal_stroke*zoom.scale()>max_stroke) stroke = max_stroke/zoom.scale(); link.style("stroke-width",stroke); circle.style("stroke-width",stroke); var text_size = nominal_text_size; if (nominal_text_size*zoom.scale()>max_text_size) text_size = max_text_size/zoom.scale(); text.style("font-size",text_size + "px"); g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); }); svg.call(zoom); resize(); force.on("tick", tick); function tick() { node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); text.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); 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(" + dx + "," + dy + ")"; }); node.attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); } function resize() { var width = $("#graph").innerWidth(); var height = $("#graph").innerHeight(); svg.attr("width", width).attr("height", height); force.size([force.size()[0]+(width-w)/zoom.scale(),force.size()[1]+(height-h)/zoom.scale()]).resume(); w = width; h = height; } //} }); 
 text { font-family: sans-serif; pointer-events: none; } html,body { width:100%; height:100%; margin:none; padding:none; } #graph { width:100%;height:100%; margin:auto; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.10/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <body> <div id="graph"></div> </body> 

and Here is What i'm trying to do : By Update function

 $(document).ready(function(){ var w = $("#graph").innerWidth(); var h = $("#graph").innerHeight(); var default_node_color = "#ccc"; var default_link_color = "red"; var nominal_base_node_size = 8; var nominal_text_size = 10; var max_text_size = 24; var nominal_stroke = 1.5; var highlight_stroke_width = 4; var max_stroke = 4.5; var min_zoom = 0.1; var max_zoom = 7; var svg = d3.select("#graph").append("svg"); var zoom = d3.behavior.zoom().scaleExtent([min_zoom,max_zoom]) var g = svg.append("g"); svg.style("cursor","move"); var dnodes = []; var dlinks = []; function findNode(id) { for (var i in dnodes) { if (dnodes[i]["id"] === id) return dnodes[i]; } } function addNode(id,name) { var newNode = findNode(id); if(newNode == undefined) { dnodes.push({"id":id,"name":name}); update(dnodes,dlinks); } } function addLink(sourceId, targetId) { var sourceNode = findNode(sourceId); var targetNode = findNode(targetId); if((sourceNode !== undefined) && (targetNode !== undefined)) { dlinks.push({"source": sourceNode, "target": targetNode}); update(dnodes,dlinks); } } $("#btnadd").click(function(){ addNode("1","2XYZ"); addNode("3","3XYZ"); addNode("4","4XYZ"); addNode("5","5XYZ"); addLink("1","2"); addLink("1","3"); addLink("1","4"); addLink("1","5"); }); var force = d3.layout.force() .linkDistance(160) .charge(-300) .friction(0.5) .size([w,h]); var nodes = force.nodes(dnodes); var links = force.links(dlinks); force.start(); function update(dnodes, dlinks) { function isConnected(sourceNodeid, destNodeid) { for(var i in dlinks) { if((dlinks[i].source.id == sourceNodeid && dlinks[i].target.id==destNodeid)||((dlinks[i].source.id == destNodeid && dlinks[i].target.id==sourceNodeid))) { return true; } } if(sourceNodeid == destNodeid) { return true; } return false; } function dragstart(d, i) { force.stop(); } function dragmove(d, i) { d.px += d3.event.dx; d.py += d3.event.dy; dx += d3.event.dx; dy += d3.event.dy; tick(); } function dragend(d, i) { d.fixed = true; tick(); } var node_drag = d3.behavior.drag() .on("dragstart", dragstart) .on("drag", dragmove) .on("dragend", dragend); var link = g.selectAll(".link") .data(dlinks) .enter().append("line") .attr("class", "link") .style("stroke-width",nominal_stroke) .style("stroke", default_link_color); var node = g.selectAll(".node") .data(dnodes) .enter().append("g") .attr("class", "node") .call(node_drag); var circle = node.append("rect") .attr("x", "-15px") .attr("y", "-15px") .attr("rx", "4") .attr("ry", "4") .attr("width", "30px") .attr("height", "30px") .attr("id", function (d) {return d.id;}) .attr("fill", "#336699"); var text = g.selectAll(".text") .data(dnodes) .enter().append("text") .attr("dy", ".35em") .attr("y","22") .style("font-size", nominal_text_size + "px") text.text(function(d) { return d.name; }) .style("text-anchor", "middle"); zoom.on("zoom", function() { var stroke = nominal_stroke; if (nominal_stroke*zoom.scale()>max_stroke) stroke = max_stroke/zoom.scale(); link.style("stroke-width",stroke); circle.style("stroke-width",stroke); var text_size = nominal_text_size; if (nominal_text_size*zoom.scale()>max_text_size) text_size = max_text_size/zoom.scale(); text.style("font-size",text_size + "px"); g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); }); svg.call(zoom); resize(); force.on("tick", tick); function tick() { node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); text.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); 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(" + dx + "," + dy + ")"; }); node.attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); } function resize() { var width = $("#graph").innerWidth(); var height = $("#graph").innerHeight(); svg.attr("width", width).attr("height", height); force.size([force.size()[0]+(width-w)/zoom.scale(),force.size()[1]+(height-h)/zoom.scale()]).resume(); w = width; h = height; } } }); 
 text { font-family: sans-serif; pointer-events: none; } html,body { width:100%; height:100%; margin:none; padding:none; } #graph { width:100%;height:100%; margin:auto; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.10/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <body> <button id="btnadd">Add</button> <div id="graph"></div> </body> 

1st link code is working fine , 2nd link code is not working properly. in 2nd link code i'm updating graph by update() function to add nodes on a button click.

addNode() addLink() i want to call on a button click. something like:

 $("#btnadd").click(function(){
addNode("1","2XYZ");
addNode("3","3XYZ");
addLink("1","2");
});

I'm not getting where i'm doing wrong.

Thanks!

You are calling the update after each node insertion.

if(newNode == undefined) 
        {
            dnodes.push({"id":id,"name":name});   
            update(dnodes,dlinks);//don't do this
        }

Instead make all your nodes and links in the button click like this(commented below).

$("#btnadd").click(function() {
    addNode("1", "2XYZ");
    addNode("3", "3XYZ");
    addNode("4", "4XYZ");
    addNode("5", "5XYZ");

    addLink("1", "2");
    addLink("1", "3");
    addLink("1", "4");
    addLink("1", "5");
    update(dnodes, dlinks);//call your update function
    force.start();//you forgot to start the force layout.
});

working code here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM