当我向D3的Force Layout添加新节点时,新节点在定位自身时忽略先前的节点,并且先前的节点变得不可拖动。 我觉得我遵循了以下逻辑:
将元素添加到数组节点和链接 更新了force.nodes(nodes)和force.links(链接) 通过.data()。输入()新数据 叫做force.start()但仍导致先前的节点断开连接。 新节点是可拖动的,并且似乎考虑了添加节点位置的最后一组并且避免了冲突,所有其他先前节点仍然可以点击,但是它们的定位被忽略并且不被更新。
这是PLNKR中的代码: http ://plnkr.co/edit/5fXZf63s73cTO37zLjNQ?p = preview
var width = 1000; var height = 600; var node_w = 30; var node_h = 30; var text_dx = -20; var text_dy = 20; var new_id = 9; var nodes = [], links = [], links_line, node_circles; var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height); var nodes = [ { "name": "Nucleus" , "size" : 25, "id" : 0 , "color":"#ac0000"}, { "name": "one" , "size" : 5 , "id": 1 , "color": "#ac0"}, { "name": "two" , "size" : 15 , "id": 2 , "color": "#ac0"}, { "name": "three" , "size" : 25 , "id": 3 , "color": "#ac0"}, { "name": "four" , "size" : 9 , "id": 4 , "color": "#ac0"}, { "name": "five" , "size" : 12 , "id": 5 , "color": "#ac0"}, { "name": "six" , "size" : 15 , "id": 6 , "color": "#ac0"}, { "name": "seven" , "size" : 41 , "id": 7 , "color": "#ac0"}, { "name": "eight" , "size" : 5 , "id": 8 , "color": "#ac0"} ]; var links = [ { "source": 0 , "target": 1 , "link_info":"r01" }, { "source": 1 , "target": 2 , "link_info":"r31" }, { "source": 1 , "target": 3 , "link_info":"r02" }, { "source": 1 , "target": 4 , "link_info":"r04" }, { "source": 0 , "target": 5 , "link_info":"r05" }, { "source": 0 , "target": 6 , "link_info":"r06" }, { "source": 0 , "target": 7 , "link_info":"r87" }, { "source": 0 , "target": 8 , "link_info":"r87" } ]; var force = d3.layout.force() .nodes(nodes) .links(links) .size([width, height]) .linkDistance(150) .charge(-1400); var drag = force.drag(); init(); function init() { force.start(); links_line = svg.selectAll("line") .data(links) .enter() .append("line") .style("stroke", "#ac0") .style("stroke-width", 1); node_circles = svg.selectAll("circle") .data(nodes) .enter() .append("circle") .style("fill", function(d) {return d.color;}) .on("dblclick", function(d, i) { addNodes(i); }) .call(drag); draw(); } function addNodes(i) { for (c=0; c < Math.floor(Math.random() * 20) + 4; c++) { nodes.push({"name": "new " + new_id,"size": (Math.floor(Math.random() * 20) + 10),"id": new_id,"color": "#333"}) links.push({"source": i,"target": new_id,"link_info": "r"+i+new_id}); new_id++; } // Update force.nodes force.nodes(nodes); // Update force.links force.links(links); // exec init() init(); } function draw() { var ticksPerRender = 1; requestAnimationFrame(function render() { force.tick(); //Update nodes node_circles.attr("cx", function(d) {return d.x - d.size / 6;}); node_circles.attr("cy", function(d) {return d.y - d.size / 6;}); node_circles.attr("r", function(d) {return d.size}); //Update Location line links_line.attr("x1", function(d) {return d.source.x;}); links_line.attr("y1", function(d) {return d.source.y;}); links_line.attr("x2", function(d) {return d.target.x;}); links_line.attr("y2", function(d) {return d.target.y;}); requestAnimationFrame(render) }); } // draw();When I add new nodes to D3's Force Layout, the new nodes ignore the previous nodes when positioning itself and the previous nodes becomes un-draggable. I feel I've followed the logic of:
Add elements to arrays nodes and links Updated force.nodes(nodes) and force.links(links) Ran through .data().enter() with new data Called force.start()But still results in previous nodes disconnects. The new nodes are draggable and appears to take into consideration the LAST SET of added nodes position and avoids collision, all other previous nodes are clickable still, but their positioning are ignored and not updated.
Here is a the code in PLNKR: http://plnkr.co/edit/5fXZf63s73cTO37zLjNQ?p=preview
var width = 1000; var height = 600; var node_w = 30; var node_h = 30; var text_dx = -20; var text_dy = 20; var new_id = 9; var nodes = [], links = [], links_line, node_circles; var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height); var nodes = [ { "name": "Nucleus" , "size" : 25, "id" : 0 , "color":"#ac0000"}, { "name": "one" , "size" : 5 , "id": 1 , "color": "#ac0"}, { "name": "two" , "size" : 15 , "id": 2 , "color": "#ac0"}, { "name": "three" , "size" : 25 , "id": 3 , "color": "#ac0"}, { "name": "four" , "size" : 9 , "id": 4 , "color": "#ac0"}, { "name": "five" , "size" : 12 , "id": 5 , "color": "#ac0"}, { "name": "six" , "size" : 15 , "id": 6 , "color": "#ac0"}, { "name": "seven" , "size" : 41 , "id": 7 , "color": "#ac0"}, { "name": "eight" , "size" : 5 , "id": 8 , "color": "#ac0"} ]; var links = [ { "source": 0 , "target": 1 , "link_info":"r01" }, { "source": 1 , "target": 2 , "link_info":"r31" }, { "source": 1 , "target": 3 , "link_info":"r02" }, { "source": 1 , "target": 4 , "link_info":"r04" }, { "source": 0 , "target": 5 , "link_info":"r05" }, { "source": 0 , "target": 6 , "link_info":"r06" }, { "source": 0 , "target": 7 , "link_info":"r87" }, { "source": 0 , "target": 8 , "link_info":"r87" } ]; var force = d3.layout.force() .nodes(nodes) .links(links) .size([width, height]) .linkDistance(150) .charge(-1400); var drag = force.drag(); init(); function init() { force.start(); links_line = svg.selectAll("line") .data(links) .enter() .append("line") .style("stroke", "#ac0") .style("stroke-width", 1); node_circles = svg.selectAll("circle") .data(nodes) .enter() .append("circle") .style("fill", function(d) {return d.color;}) .on("dblclick", function(d, i) { addNodes(i); }) .call(drag); draw(); } function addNodes(i) { for (c=0; c < Math.floor(Math.random() * 20) + 4; c++) { nodes.push({"name": "new " + new_id,"size": (Math.floor(Math.random() * 20) + 10),"id": new_id,"color": "#333"}) links.push({"source": i,"target": new_id,"link_info": "r"+i+new_id}); new_id++; } // Update force.nodes force.nodes(nodes); // Update force.links force.links(links); // exec init() init(); } function draw() { var ticksPerRender = 1; requestAnimationFrame(function render() { force.tick(); //Update nodes node_circles.attr("cx", function(d) {return d.x - d.size / 6;}); node_circles.attr("cy", function(d) {return d.y - d.size / 6;}); node_circles.attr("r", function(d) {return d.size}); //Update Location line links_line.attr("x1", function(d) {return d.source.x;}); links_line.attr("y1", function(d) {return d.source.y;}); links_line.attr("x2", function(d) {return d.target.x;}); links_line.attr("y2", function(d) {return d.target.y;}); requestAnimationFrame(render) }); } // draw();最满意答案
更新d3可视化遵循输入,更新和退出工作流程( 在此处和此处开始阅读)。
试试这个:
function init() { force.start(); links_line = svg.selectAll("line") .data(links); links_line .enter() .append("line") .style("stroke", "#ac0") .style("stroke-width", 1); links_line.exit().remove(); node_circles = svg.selectAll("circle") .data(nodes); node_circles .enter() .append("circle") .style("fill", function(d) {return d.color;}) .on("dblclick", function(d, i) { addNodes(i); }) .call(drag); draw(); }更新的例子 。
Updating a d3 visualization follows an enter, update, and exit workflow (start your reading here and here).
Try this instead:
function init() { force.start(); links_line = svg.selectAll("line") .data(links); links_line .enter() .append("line") .style("stroke", "#ac0") .style("stroke-width", 1); links_line.exit().remove(); node_circles = svg.selectAll("circle") .data(nodes); node_circles .enter() .append("circle") .style("fill", function(d) {return d.color;}) .on("dblclick", function(d, i) { addNodes(i); }) .call(drag); draw(); }Updated example.
更多推荐
发布评论