[76] | 1 | <!DOCTYPE html> |
---|
| 2 | <html> |
---|
| 3 | <head> |
---|
| 4 | <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> |
---|
| 5 | <title>Node-Link Tree</title> |
---|
| 6 | <script type="text/javascript" src="../../d3.js"></script> |
---|
| 7 | <script type="text/javascript" src="../../d3.layout.js"></script> |
---|
| 8 | <style type="text/css"> |
---|
| 9 | |
---|
| 10 | .node { |
---|
| 11 | stroke: #fff; |
---|
| 12 | stroke-width: 2px; |
---|
| 13 | } |
---|
| 14 | |
---|
| 15 | .link { |
---|
| 16 | fill: none; |
---|
| 17 | stroke: #000; |
---|
| 18 | } |
---|
| 19 | |
---|
| 20 | </style> |
---|
| 21 | </head> |
---|
| 22 | <body> |
---|
| 23 | <script type="text/javascript"> |
---|
| 24 | |
---|
| 25 | var w = 960, |
---|
| 26 | h = 500, |
---|
| 27 | root = {}, |
---|
| 28 | data = [root], |
---|
| 29 | tree = d3.layout.tree().size([w - 20, h - 20]), |
---|
| 30 | diagonal = d3.svg.diagonal(), |
---|
| 31 | duration = 750, |
---|
| 32 | timer = setInterval(update, duration); |
---|
| 33 | |
---|
| 34 | var vis = d3.select("body").append("svg:svg") |
---|
| 35 | .attr("width", w) |
---|
| 36 | .attr("height", h) |
---|
| 37 | .append("svg:g") |
---|
| 38 | .attr("transform", "translate(10, 10)"); |
---|
| 39 | |
---|
| 40 | vis.selectAll("circle") |
---|
| 41 | .data(tree(root)) |
---|
| 42 | .enter().append("svg:circle") |
---|
| 43 | .attr("class", "node") |
---|
| 44 | .attr("r", 3.5) |
---|
| 45 | .attr("cx", x) |
---|
| 46 | .attr("cy", y); |
---|
| 47 | |
---|
| 48 | function update() { |
---|
| 49 | if (data.length >= 500) return clearInterval(timer); |
---|
| 50 | |
---|
| 51 | // Add a new datum to a random parent. |
---|
| 52 | var d = {id: data.length}, parent = data[~~(Math.random() * data.length)]; |
---|
| 53 | if (parent.children) parent.children.push(d); else parent.children = [d]; |
---|
| 54 | data.push(d); |
---|
| 55 | |
---|
| 56 | // Compute the new tree layout. We'll stash the old layout in the data. |
---|
| 57 | var nodes = tree.nodes(root); |
---|
| 58 | |
---|
| 59 | // Update the nodes⊠|
---|
| 60 | var node = vis.selectAll("circle.node") |
---|
| 61 | .data(nodes, function(d) { return d.id; }); |
---|
| 62 | |
---|
| 63 | // Enter any new nodes at the parent's previous position. |
---|
| 64 | node.enter().append("svg:circle") |
---|
| 65 | .attr("class", "node") |
---|
| 66 | .attr("r", 3.5) |
---|
| 67 | .attr("cx", function(d) { return d.parent.x0; }) |
---|
| 68 | .attr("cy", function(d) { return d.parent.y0; }) |
---|
| 69 | .transition() |
---|
| 70 | .duration(duration) |
---|
| 71 | .attr("cx", x) |
---|
| 72 | .attr("cy", y); |
---|
| 73 | |
---|
| 74 | // Transition nodes to their new position. |
---|
| 75 | node.transition() |
---|
| 76 | .duration(duration) |
---|
| 77 | .attr("cx", x) |
---|
| 78 | .attr("cy", y); |
---|
| 79 | |
---|
| 80 | // Update the links⊠|
---|
| 81 | var link = vis.selectAll("path.link") |
---|
| 82 | .data(tree.links(nodes), function(d) { return d.target.id; }); |
---|
| 83 | |
---|
| 84 | // Enter any new links at the parent's previous position. |
---|
| 85 | link.enter().insert("svg:path", "circle") |
---|
| 86 | .attr("class", "link") |
---|
| 87 | .attr("d", function(d) { |
---|
| 88 | var o = {x: d.source.x0, y: d.source.y0}; |
---|
| 89 | return diagonal({source: o, target: o}); |
---|
| 90 | }) |
---|
| 91 | .transition() |
---|
| 92 | .duration(duration) |
---|
| 93 | .attr("d", diagonal); |
---|
| 94 | |
---|
| 95 | // Transition links to their new position. |
---|
| 96 | link.transition() |
---|
| 97 | .duration(duration) |
---|
| 98 | .attr("d", diagonal); |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | function x(d) { |
---|
| 102 | return d.x0 = d.x; |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | function y(d) { |
---|
| 106 | return d.y0 = d.y; |
---|
| 107 | } |
---|
| 108 | |
---|
| 109 | </script> |
---|
| 110 | </body> |
---|
| 111 | </html> |
---|