學習 force layout 及 transition
遇到的問題:不知道是不是 bug,當 node fixed 的時候且每個 node 的 x,y 都靜止不變後,double click node 並不會讓 node 彈回去
學習 force layout 及 transition
遇到的問題:不知道是不是 bug,當 node fixed 的時候且每個 node 的 x,y 都靜止不變後,double click node 並不會讓 node 彈回去
| { | |
| "nodes": [ | |
| {"x": 469, "y": 410}, | |
| {"x": 493, "y": 364}, | |
| {"x": 442, "y": 365}, | |
| {"x": 467, "y": 314}, | |
| {"x": 477, "y": 248}, | |
| {"x": 425, "y": 207}, | |
| {"x": 402, "y": 155}, | |
| {"x": 369, "y": 196}, | |
| {"x": 350, "y": 148}, | |
| {"x": 539, "y": 222}, | |
| {"x": 594, "y": 235}, | |
| {"x": 582, "y": 185}, | |
| {"x": 633, "y": 200} | |
| ], | |
| "links": [ | |
| {"source": 0, "target": 1}, | |
| {"source": 1, "target": 2}, | |
| {"source": 2, "target": 0}, | |
| {"source": 1, "target": 3}, | |
| {"source": 3, "target": 2}, | |
| {"source": 3, "target": 4}, | |
| {"source": 4, "target": 5}, | |
| {"source": 5, "target": 6}, | |
| {"source": 5, "target": 7}, | |
| {"source": 6, "target": 7}, | |
| {"source": 6, "target": 8}, | |
| {"source": 7, "target": 8}, | |
| {"source": 9, "target": 4}, | |
| {"source": 9, "target": 11}, | |
| {"source": 9, "target": 10}, | |
| {"source": 10, "target": 11}, | |
| {"source": 11, "target": 12}, | |
| {"source": 12, "target": 10} | |
| ] | |
| } |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .link { | |
| stroke: #000; | |
| stroke-width: 1.5px; | |
| } | |
| .node { | |
| cursor: move; | |
| fill: #ccc; | |
| stroke-width: 0px; | |
| } | |
| .node.fixed { | |
| stroke: #000; | |
| stroke-width: 2.5px; | |
| } | |
| </style> | |
| <body> | |
| <script src="//d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500; | |
| var force = d3.layout.force() | |
| .size([width, height]) | |
| .charge(-300) | |
| .linkDistance(40) | |
| .on("tick", tick); | |
| var drag = force.drag() | |
| .on("dragstart", dragstart); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height); | |
| var link = svg.selectAll(".link"), | |
| node = svg.selectAll(".node"); | |
| var color = d3.scale.category10(); | |
| d3.json("graph.json", function(error, graph) { | |
| if (error) throw error; | |
| force | |
| .nodes(graph.nodes) | |
| .links(graph.links) | |
| .start(); | |
| link = link.data(graph.links) | |
| .enter().append("line") | |
| .attr("class", "link"); | |
| node = node.data(graph.nodes) | |
| .enter().append("circle") | |
| .attr("class", "node") | |
| .attr("r", 12) | |
| .on("dblclick", dblclick) | |
| .call(drag); | |
| node | |
| .transition() | |
| .delay(function(d, i) { return i * 200; }) | |
| .duration(1000) | |
| .attr("r", 16) | |
| .style("fill", function(d, i) { return color(i); }); | |
| }); | |
| function tick() { | |
| link.attr("x1", function(d) { return d.source.x; }) | |
| .attr("y1", function(d) { return d.source.y; }) | |
| .attr("x2", function(d) { return d.target.x; }) | |
| .attr("y2", function(d) { return d.target.y; }); | |
| node.attr("cx", function(d) { return d.x; }) | |
| .attr("cy", function(d) { return d.y; }); | |
| } | |
| function dblclick(d) { | |
| d3.select(this).classed("fixed", d.fixed = false); | |
| } | |
| function dragstart(d) { | |
| d3.select(this).classed("fixed", d.fixed = true); | |
| } | |
| </script> |