2015-04-24 85 views
0

如何在力佈局d3中使用碰撞檢測功能。當我搜索我得到這段代碼,但如果考慮佈局不包含任何circle.It只包含一些圖像和文本組。 那麼我該如何重寫這個函數。使用組節點進行力線佈局碰撞檢測

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; 
};} 
+0

是高度和寬度相等的所有節點? – Gilsha

+0

對於所有節點,高度和寬度均相等 – fekkyDEV

回答

1

由於每個節點的高度和寬度是一樣的,唯一需要的變化將是使用的group代替node.radius大小在collide功能。確保有一個獨特的數據綁定到每個節點。

var width = 960, 
 
    height = 500; 
 

 
var nodes = d3.range(200).map(function() { 
 
     return { 
 
      radius: Math.random() * 12 + 4 
 
     }; 
 
    }), 
 
    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); 
 

 
var node = svg.selectAll(".node") 
 
    .data(nodes.slice(1)) 
 
    .enter() 
 
    .append("g") 
 
    .attr("class", "node") 
 
    .attr("id",function(d,i){ return d.id = "node"+i; }); 
 

 
node.append("svg:image") 
 
    .attr("xlink:href", "http://www.clker.com/cliparts/g/l/R/7/h/u/teamstijl-person-icon-blue.svg") 
 
    .attr("width", "30px") 
 
    .attr("height", "30px"); 
 

 
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(".node") 
 
     .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(); 
 
}); 
 

 
function collide(node) { 
 
    var nodeEl = svg.selectAll("g.node") 
 
     .filter(function(d, i) { 
 
      return node.id == d.id 
 
     }).node(); 
 
    var nodeSize = nodeEl.getBBox().height+16;//You can remove/reduce this static value 16 to decrease the gap between nodes. 
 
    var r = nodeSize/2 + 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 = nodeSize/2 + 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 src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>