2015-11-04 133 views
0

我试图修改现有的碰撞检测程序在http://mbostock.github.io/d3/talk/20111018/collision.html删除从D3列表中的节点,并重新布局

我想这样说,它的每个节点上的标签编辑代码,我可以删除节点通过停止动画并单击要删除的节点。这里是编辑代码的样子:

<!DOCTYPE html> 
<html> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 
    <script type="text/javascript" src="d3/d3.js"></script> 
    <script type="text/javascript" src="d3/d3.geom.js"></script> 
    <script type="text/javascript" src="d3/d3.layout.js"></script> 
<script type="text/javascript" src="d3/d3.min.js"></script> 
    <link type="text/css" rel="stylesheet" href="style.css"/> 
    <style type="text/css"> 

circle { 
    stroke: #000; 
    stroke-opacity: .5; 
} 

    </style> 
    </head> 
    <body> 
    <div id="body"> 
     <div id="footer"> 
     Collision Detection 
     <div class="hint">move the mouse to repel nodes</div> 
     </div> 
    </div> 
    <script type="text/javascript"> 

var width = 1280, 
    height = 800; 

var labels = [ 
    "hello", 
    "goodbye", 
    "purple", 
    "blue", 
    "green", 
    "pink", 
    "yellow", 
    "white", 
    "black", 
    "brown", 
    "cat", 
    "dog", 
    "bird", 
    "snake", 
    "turtle"]; 

var i = 0; 

var nodes = d3.range(200).map(function() { return {radius: Math.random() * 12 + 4, label: labels[Math.floor(Math.random() * 15)]}; }), 
    root = nodes[0], 
    color = d3.scale.category10(); 

root.radius = 0; 
root.fixed = true; 

var force = d3.layout.force() 
    .gravity(0.05) 
    .charge(function(d, i) { return i ? 0 : -2000; }) 
    .nodes(nodes) 
    .size([width, height]); 

force.start(); 

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

g = svg.selectAll("circle") 
    .data(nodes.slice(1)) 
    .enter().append("g") 

    g.append('circle') 
    .attr('cx', 0) 
    .attr('cy', 0) 
    .attr("r", function(d) { return d.radius; }) 
    .style("fill", function(d, i) { return color(i % 20); }) 

    g.append('text') 
    .text(function(d){return d.label}) 
    .attr('x', -15) 
    .attr('y', 5) 

force.on("tick", function(e) { 
    var q = d3.geom.quadtree(nodes), 
     i = 0, 
     n = nodes.length; 

    while (++i < n) q.visit(collide(nodes[i])); 

    svg.selectAll("g") 
    .attr('transform', function(d){return "translate("+d.x+","+d.y+")"}) 
}); 

svg.on("mousemove", function() { 
    var p1 = d3.mouse(this); 
    root.px = p1[0]; 
    root.py = p1[1]; 
    //force.resume(); 
}); 

svg.on("click", function() { 
    if(force.alpha()) { 
    force.stop(); 
    } else { 
    force.resume(); 
    } 
}); 

svg.selectAll("g").on("click", function() { 
    d3.event.stopPropagation(); 
    this.remove(); 
    //nodes.removeChild(this.remove()); 
    //var deleteNode = this.selection.node(); 

    force.on("tick", function(x) { 
    var a = d3.geom.quadtree(nodes), 
     b = 0, 
     c = nodes.length; 

    while(++b < c) a.visit(collide(nodes[b])); 

    //svg.selectAll("g") 
    //.attr('transform', function(d){return "translate("+d.x+"."+d.y+")"}) 
    }); 

}); 


function collide(node) { 
    var r = node.radius + 16, 
     nx1 = node.x - r, 
     nx2 = node.x + r, 
     ny1 = node.y - r, 
     ny2 = node.y + r; 
    return function(quad, x1, y1, x2, y2) { 
    if (quad.point && (quad.point !== node)) { 
     var x = node.x - quad.point.x, 
      y = node.y - quad.point.y, 
      l = Math.sqrt(x * x + y * y), 
      r = node.radius + quad.point.radius; 
     if (l < r) { 
     l = (l - r)/l * .5; 
     node.x -= x *= l; 
     node.y -= y *= l; 
     quad.point.x += x; 
     quad.point.y += y; 
     } 
    } 
    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
    }; 
} 
    </script> 
    </body> 
</html> 

我遇到的麻烦是从节点阵列中删除节点并重新设置布局。现在它隐藏了实际的圆和标签,但是当动画重新启动时,它仍然有一个节点没有实际删除的位置。你可以看到我用this.remove()来隐藏节点,但它实际上并没有删除节点。下面的代码是我尝试过的其他东西,为了删除节点,然后重置布局,但没有成功。我对D3并不熟悉,我无法理解正在发生的事情,实际上是从D3中的一个数组中删除了一个节点。

回答

1

要重新布局后删除一个节点的

svg.selectAll("g").on("click", function() { 
    d3.event.stopPropagation(); 
    this.remove(); 
    force.resume();//restart the layout 
}); 

点击SVG将停止滴答点击回将开始滴答布局再次

svg.on("click", function() { 
    if(force.alpha()) { 
    force.stop(); 
    } else { 
    force.resume();//start the layout 
    } 
}); 

工作代码here

希望这有助于!

+0

有点晚了,但你还没有完全解决它。该节点从DOM中删除,但不从数据中删除。所以我已经添加了我自己的答案,以添加到你:))希望它可以帮助其他人 – thatOneGuy

1

上面的答案几乎就在那里。您删除了该元素,但不会将其从数据中删除。所以我编辑了小提琴,并将此:

svg.selectAll("g").on("click", function(d) { 
    d3.event.stopPropagation(); 
    this.remove(); 
    force.resume(); 

    nodes.splice(d.index,1) //this deletes the node from the data at the nodes index 
    console.log(nodes.length) 
}); 

更新小提琴:http://jsfiddle.net/8t1Lgsk6/2/

+0

感谢您找到该错误+1 :) – Cyril