2015-11-04 136 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