Нет описания

Force_Based_Label.html 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <!-- http://bl.ocks.org/MoritzStefaner/1377729 -->
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
  3. <html lang="en">
  4. <head>
  5. <meta charset="utf-8">
  6. <title>Force based label placement</title>
  7. <script type="text/javascript" src="https://mbostock.github.com/d3/d3.js?2.6.0"></script>
  8. <script type="text/javascript" src="https://mbostock.github.com/d3/d3.layout.js?2.6.0"></script>
  9. <script type="text/javascript" src="https://mbostock.github.com/d3/d3.geom.js?2.6.0"></script>
  10. </head>
  11. <body>
  12. <script type="text/javascript" charset="utf-8">
  13. var w = 960, h = 500;
  14. var labelDistance = 0;
  15. var vis = d3.select("body").append("svg:svg").attr("width", w).attr("height", h);
  16. var nodes = [];
  17. var labelAnchors = [];
  18. var labelAnchorLinks = [];
  19. var links = [];
  20. for(var i = 0; i < 30; i++) {
  21. var node = {
  22. label : "node " + i
  23. };
  24. nodes.push(node);
  25. labelAnchors.push({
  26. node : node
  27. });
  28. labelAnchors.push({
  29. node : node
  30. });
  31. };
  32. for(var i = 0; i < nodes.length; i++) {
  33. for(var j = 0; j < i; j++) {
  34. if(Math.random() > .95)
  35. links.push({
  36. source : i,
  37. target : j,
  38. weight : Math.random()
  39. });
  40. }
  41. labelAnchorLinks.push({
  42. source : i * 2,
  43. target : i * 2 + 1,
  44. weight : 1
  45. });
  46. };
  47. var force = d3.layout.force().size([w, h]).nodes(nodes).links(links).gravity(1).linkDistance(50).charge(-3000).linkStrength(function(x) {
  48. return x.weight * 10
  49. });
  50. force.start();
  51. var force2 = d3.layout.force().nodes(labelAnchors).links(labelAnchorLinks).gravity(0).linkDistance(0).linkStrength(8).charge(-100).size([w, h]);
  52. force2.start();
  53. var link = vis.selectAll("line.link").data(links).enter().append("svg:line").attr("class", "link").style("stroke", "#CCC");
  54. var node = vis.selectAll("g.node").data(force.nodes()).enter().append("svg:g").attr("class", "node");
  55. node.append("svg:circle").attr("r", 5).style("fill", "#555").style("stroke", "#FFF").style("stroke-width", 3);
  56. node.call(force.drag);
  57. var anchorLink = vis.selectAll("line.anchorLink").data(labelAnchorLinks)//.enter().append("svg:line").attr("class", "anchorLink").style("stroke", "#999");
  58. var anchorNode = vis.selectAll("g.anchorNode").data(force2.nodes()).enter().append("svg:g").attr("class", "anchorNode");
  59. anchorNode.append("svg:circle").attr("r", 0).style("fill", "#FFF");
  60. anchorNode.append("svg:text").text(function(d, i) {
  61. return i % 2 == 0 ? "" : d.node.label
  62. }).style("fill", "#555").style("font-family", "Arial").style("font-size", 12);
  63. var updateLink = function() {
  64. this.attr("x1", function(d) {
  65. return d.source.x;
  66. }).attr("y1", function(d) {
  67. return d.source.y;
  68. }).attr("x2", function(d) {
  69. return d.target.x;
  70. }).attr("y2", function(d) {
  71. return d.target.y;
  72. });
  73. }
  74. var updateNode = function() {
  75. this.attr("transform", function(d) {
  76. return "translate(" + d.x + "," + d.y + ")";
  77. });
  78. }
  79. force.on("tick", function() {
  80. force2.start();
  81. node.call(updateNode);
  82. anchorNode.each(function(d, i) {
  83. if(i % 2 == 0) {
  84. d.x = d.node.x;
  85. d.y = d.node.y;
  86. } else {
  87. var b = this.childNodes[1].getBBox();
  88. var diffX = d.x - d.node.x;
  89. var diffY = d.y - d.node.y;
  90. var dist = Math.sqrt(diffX * diffX + diffY * diffY);
  91. var shiftX = b.width * (diffX - dist) / (dist * 2);
  92. shiftX = Math.max(-b.width, Math.min(0, shiftX));
  93. var shiftY = 5;
  94. this.childNodes[1].setAttribute("transform", "translate(" + shiftX + "," + shiftY + ")");
  95. }
  96. });
  97. anchorNode.call(updateNode);
  98. link.call(updateLink);
  99. anchorLink.call(updateLink);
  100. });
  101. </script>
  102. </body>
  103. </html>