| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- <!-- http://bl.ocks.org/MoritzStefaner/1377729 -->
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>Force based label placement</title>
- <script type="text/javascript" src="https://mbostock.github.com/d3/d3.js?2.6.0"></script>
- <script type="text/javascript" src="https://mbostock.github.com/d3/d3.layout.js?2.6.0"></script>
- <script type="text/javascript" src="https://mbostock.github.com/d3/d3.geom.js?2.6.0"></script>
- </head>
- <body>
- <script type="text/javascript" charset="utf-8">
- var w = 960, h = 500;
-
- var labelDistance = 0;
-
- var vis = d3.select("body").append("svg:svg").attr("width", w).attr("height", h);
-
- var nodes = [];
- var labelAnchors = [];
- var labelAnchorLinks = [];
- var links = [];
-
- for(var i = 0; i < 30; i++) {
- var node = {
- label : "node " + i
- };
- nodes.push(node);
- labelAnchors.push({
- node : node
- });
- labelAnchors.push({
- node : node
- });
- };
-
- for(var i = 0; i < nodes.length; i++) {
- for(var j = 0; j < i; j++) {
- if(Math.random() > .95)
- links.push({
- source : i,
- target : j,
- weight : Math.random()
- });
- }
- labelAnchorLinks.push({
- source : i * 2,
- target : i * 2 + 1,
- weight : 1
- });
- };
-
- var force = d3.layout.force().size([w, h]).nodes(nodes).links(links).gravity(1).linkDistance(50).charge(-3000).linkStrength(function(x) {
- return x.weight * 10
- });
-
-
- force.start();
-
- var force2 = d3.layout.force().nodes(labelAnchors).links(labelAnchorLinks).gravity(0).linkDistance(0).linkStrength(8).charge(-100).size([w, h]);
- force2.start();
-
- var link = vis.selectAll("line.link").data(links).enter().append("svg:line").attr("class", "link").style("stroke", "#CCC");
-
- var node = vis.selectAll("g.node").data(force.nodes()).enter().append("svg:g").attr("class", "node");
- node.append("svg:circle").attr("r", 5).style("fill", "#555").style("stroke", "#FFF").style("stroke-width", 3);
- node.call(force.drag);
-
-
- var anchorLink = vis.selectAll("line.anchorLink").data(labelAnchorLinks)//.enter().append("svg:line").attr("class", "anchorLink").style("stroke", "#999");
-
- var anchorNode = vis.selectAll("g.anchorNode").data(force2.nodes()).enter().append("svg:g").attr("class", "anchorNode");
- anchorNode.append("svg:circle").attr("r", 0).style("fill", "#FFF");
- anchorNode.append("svg:text").text(function(d, i) {
- return i % 2 == 0 ? "" : d.node.label
- }).style("fill", "#555").style("font-family", "Arial").style("font-size", 12);
-
- var updateLink = function() {
- this.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;
- });
-
- }
-
- var updateNode = function() {
- this.attr("transform", function(d) {
- return "translate(" + d.x + "," + d.y + ")";
- });
-
- }
-
- force.on("tick", function() {
-
- force2.start();
-
- node.call(updateNode);
-
- anchorNode.each(function(d, i) {
- if(i % 2 == 0) {
- d.x = d.node.x;
- d.y = d.node.y;
- } else {
- var b = this.childNodes[1].getBBox();
-
- var diffX = d.x - d.node.x;
- var diffY = d.y - d.node.y;
-
- var dist = Math.sqrt(diffX * diffX + diffY * diffY);
-
- var shiftX = b.width * (diffX - dist) / (dist * 2);
- shiftX = Math.max(-b.width, Math.min(0, shiftX));
- var shiftY = 5;
- this.childNodes[1].setAttribute("transform", "translate(" + shiftX + "," + shiftY + ")");
- }
- });
-
- anchorNode.call(updateNode);
-
- link.call(updateLink);
- anchorLink.call(updateLink);
-
- });
-
- </script>
- </body>
- </html>
|