概要 实例 介绍 源码

碰撞检测

源文件:index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
  5. <script type="text/javascript" src="/d3/d3.js"></script>
  6. <script type="text/javascript" src="/d3/d3.geom.js"></script>
  7. <script type="text/javascript" src="/d3/d3.layout.js"></script>
  8. <link type="text/css" rel="stylesheet" href="style.css"/>
  9. <style type="text/css">
  10. circle {
  11. stroke: #000;
  12. stroke-opacity: .5;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <div id="body">
  18. <div id="footer">
  19. Collision Detection
  20. <div class="hint">move the mouse to repel nodes</div>
  21. </div>
  22. </div>
  23. <script type="text/javascript">
  24. var w = 1280,
  25. h = 800;
  26. var nodes = d3.range(200).map(function() { return {radius: Math.random() * 12 + 4}; }),
  27. color = d3.scale.category10();
  28. var force = d3.layout.force()
  29. .gravity(0.05)
  30. .charge(function(d, i) { return i ? 0 : -2000; })
  31. .nodes(nodes)
  32. .size([w, h]);
  33. var root = nodes[0];
  34. root.radius = 0;
  35. root.fixed = true;
  36. force.start();
  37. var svg = d3.select("#body").append("svg:svg")
  38. .attr("width", w)
  39. .attr("height", h);
  40. svg.selectAll("circle")
  41. .data(nodes.slice(1))
  42. .enter().append("svg:circle")
  43. .attr("r", function(d) { return d.radius - 2; })
  44. .style("fill", function(d, i) { return color(i % 3); });
  45. force.on("tick", function(e) {
  46. var q = d3.geom.quadtree(nodes),
  47. i = 0,
  48. n = nodes.length;
  49. while (++i < n) {
  50. q.visit(collide(nodes[i]));
  51. }
  52. svg.selectAll("circle")
  53. .attr("cx", function(d) { return d.x; })
  54. .attr("cy", function(d) { return d.y; });
  55. });
  56. svg.on("mousemove", function() {
  57. var p1 = d3.svg.mouse(this);
  58. root.px = p1[0];
  59. root.py = p1[1];
  60. force.resume();
  61. });
  62. function collide(node) {
  63. var r = node.radius + 16,
  64. nx1 = node.x - r,
  65. nx2 = node.x + r,
  66. ny1 = node.y - r,
  67. ny2 = node.y + r;
  68. return function(quad, x1, y1, x2, y2) {
  69. if (quad.point && (quad.point !== node)) {
  70. var x = node.x - quad.point.x,
  71. y = node.y - quad.point.y,
  72. l = Math.sqrt(x * x + y * y),
  73. r = node.radius + quad.point.radius;
  74. if (l < r) {
  75. l = (l - r) / l * .5;
  76. node.x -= x *= l;
  77. node.y -= y *= l;
  78. quad.point.x += x;
  79. quad.point.y += y;
  80. }
  81. }
  82. return x1 > nx2
  83. || x2 < nx1
  84. || y1 > ny2
  85. || y2 < ny1;
  86. };
  87. }
  88. </script>
  89. </body>
  90. </html>

源文件:style.css

  1. body {
  2. background: url(texture-noise.png);
  3. overflow: hidden;
  4. margin: 0;
  5. font-size: 14px;
  6. font-family: "Helvetica Neue", Helvetica;
  7. }
  8. #chart, #header, #footer {
  9. position: absolute;
  10. top: 0;
  11. }
  12. #header, #footer {
  13. z-index: 1;
  14. display: block;
  15. font-size: 36px;
  16. font-weight: 300;
  17. text-shadow: 0 1px 0 #fff;
  18. }
  19. #header.inverted, #footer.inverted {
  20. color: #fff;
  21. text-shadow: 0 1px 4px #000;
  22. }
  23. #header {
  24. top: 80px;
  25. left: 140px;
  26. width: 1000px;
  27. }
  28. #footer {
  29. top: 680px;
  30. right: 140px;
  31. text-align: right;
  32. }
  33. rect {
  34. fill: none;
  35. pointer-events: all;
  36. }
  37. pre {
  38. font-size: 18px;
  39. }
  40. line {
  41. stroke: #000;
  42. stroke-width: 1.5px;
  43. }
  44. .string, .regexp {
  45. color: #f39;
  46. }
  47. .keyword {
  48. color: #00c;
  49. }
  50. .comment {
  51. color: #777;
  52. font-style: oblique;
  53. }
  54. .number {
  55. color: #369;
  56. }
  57. .class, .special {
  58. color: #1181B8;
  59. }
  60. a:link, a:visited {
  61. color: #000;
  62. text-decoration: none;
  63. }
  64. a:hover {
  65. color: #666;
  66. }
  67. .hint {
  68. position: absolute;
  69. right: 0;
  70. width: 1280px;
  71. font-size: 12px;
  72. color: #999;
  73. }