2015-10-17 67 views
0

小圆圈,在较大的圆位置几套上同一SVG圈与D3.JS

这里编组不同的半径是我迄今为止 - 一个圆圈:http://jsfiddle.net/dmitrychuba/hqy6q6qv/

(function() { 
var rand = function (min, max) { 
    return Math.floor(Math.random() * (max - min + 1)) + min; 
}; 

var width = 400, 
    height = 400, 
    root = { 
     "name": "A", 
      "size": 12323, 
      "children": [{ 
      "name": "B", 
       "size": 3938 
     }, { 
      "name": "C", 
       "size": 3812 
     }, { 
      "name": "D", 
       "size": 6714 
     }, { 
      "name": "E", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, { 
      "name": "D1", 
       "size": 6714 
     }, { 
      "name": "E1", 
       "size": 743 
     }, { 
      "name": "B1", 
       "size": 3938 
     }, { 
      "name": "C1", 
       "size": 3812 
     }, 

     ] 
    }; 
var force = d3.layout.force() 
    .linkDistance(function (d) { 
    return 100; 
}) // link distance between the nodes 
.charge(-200) // charge that repel nodes from each other 
.gravity(0.1) 
    .size([width, height]) 
    .on("tick", tick); 

var svg = d3.select("#main-container").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

var link = svg.selectAll(".link"), 
    node = svg.selectAll(".node"); 
//Fix the position of the nodes and doesnt allow them to move out of the screen 
flatten(root); //to set ids 

update(); 

function update() { 
    var nodes = flatten(root), 
     links = d3.layout.tree().links(nodes); 
    // Restart the force layout. 
    force.nodes(nodes) 
     .links(links) 
     .start(); 


    // Update nodes. 
    node = node.data(nodes, function (d) { 
     return d.id; 
    }); 

    node.exit().remove(); 

    var nodeEnter = node.enter().append("g") 
     .attr("class", "node"); 

    //Adjusting the node sizes according to the children 
    nodeEnter.append("circle") 
     .style("display", function (d) { 
     return d.children ? "none" : ""; 
    }) 
     .attr("stroke", 'black') 
     .attr("r", function (d) { 
     var r = rand(6, 18); 
     return d._children ? d.size ? 14 : 18 : d.children ? 24 : r; 
    }); 

    nodeEnter.append("text") 
     .attr("dy", ".35em") 
     .text(function (d) { 
     return d.name; 
    }).style("display", function (d) { 
     return d.children ? "none" : ""; 
    }) 
     .style("font-size", function (d) { 
     return 10; 
    }); 

    node.select("circle") 
     .style("fill", color); 
} 

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("transform", function (d) { 
     return "translate(" + d.x + "," + d.y + ")"; 
    }); 
} 

function color(d) { 
    return "#fd8d3c"; 
} 


// Returns a list of all nodes under the root. 
function flatten(root) { 
    var nodes = [], 
     i = 0; 

    function recurse(node) { 
     if (node.children) node.children.forEach(recurse); 
     if (!node.id) node.id = ++i; 
     nodes.push(node); 
    } 

    recurse(root); 
    return nodes; 
} 

setInterval(function() { 
    force.alpha(.1); 
}, 100); 
})(); 

为了创建几个圈,我只是'循环'在这里:http://jsfiddle.net/dmitrychuba/hm72c74a/,但这样我有几个SVG元素,这是不是很好,因为我不能让他们像上面的图像(彼此更接近)的位置。此外,我还需要一些较小的实心圆以及未来的放大/缩小功能。

所以我的问题是:有没有一种方法可以在同一个SVG上有多组圆,并且有几个实心圆,并且可以放大/缩小?

感谢 梅德

回答

2

这是更好地把所有圈子群体和各个圈子的一组元素中,而不是将它们作为单独的SVG。尝试如下所示。

var rand = function(min, max) { 
 
    return Math.floor(Math.random() * (max - min + 1)) + min; 
 
}; 
 

 
var width = 400, 
 
    height = 400, 
 
    root = { 
 
    "name": "A", 
 
    "size": 12323, 
 
    "children": [{ 
 
     "name": "B", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, { 
 
     "name": "D1", 
 
     "size": 6714 
 
     }, { 
 
     "name": "E1", 
 
     "size": 743 
 
     }, { 
 
     "name": "B1", 
 
     "size": 3938 
 
     }, { 
 
     "name": "C1", 
 
     "size": 3812 
 
     }, 
 

 
    ] 
 
    }; 
 

 
var zoom = d3.behavior.zoom() 
 
    .scaleExtent([1, 10]) 
 
    .on("zoom", zoomed); 
 
var color = d3.scale.category10(); 
 
var svg = d3.select("#main-container").append("svg") 
 
    .attr("width", width * 3) 
 
    .attr("height", height * 2) 
 
    .call(zoom); 
 
var mainContainer = svg.append("g"); 
 

 
function zoomed() { 
 
    mainContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
 
} 
 
var positions = [ 
 
    [0, 0], 
 
    [width, 0], 
 
    [width * 2, 0], 
 
    [width - 200, height], 
 
    [width * 2 - 200, height] 
 
]; 
 

 
function addCircle(x, y) { 
 
    mainContainer.append("circle") 
 
    .style("fill", "#3D91B2") 
 
    .attr("cx", x) 
 
    .attr("cy", y) 
 
    .attr("r", 50); 
 
} 
 
addCircle(width, height - 70); 
 
addCircle(width * 2, height - 70); 
 

 

 
for (var i = 0; i < 5; i++) 
 
    (function() { 
 
    var force = d3.layout.force() 
 
     .linkDistance(function(d) { 
 
     return 100; 
 
     }) // link distance between the nodes 
 
     .charge(-200) // charge that repel nodes from each other 
 
     .gravity(0.1) 
 
     .size([width, height]) 
 
     .on("tick", tick); 
 

 
    var gContainer = mainContainer.append("g") 
 
     .attr("transform", "translate(" + positions[i][0] + "," + positions[i][1] + ")"); 
 

 
    var link = gContainer.selectAll(".link"), 
 
     node = gContainer.selectAll(".node"); 
 
    //Fix the position of the nodes and doesnt allow them to move out of the screen 
 
    flatten(root); //to set ids 
 

 
    update(i); 
 

 
    function update(colorIdx) { 
 
     var nodes = flatten(root), 
 
     links = d3.layout.tree().links(nodes); 
 
     // Restart the force layout. 
 
     force.nodes(nodes) 
 
     .links(links) 
 
     .start(); 
 

 

 
     // Update nodes. 
 
     node = node.data(nodes, function(d) { 
 
     return d.id; 
 
     }); 
 

 
     node.exit().remove(); 
 

 
     var nodeEnter = node.enter().append("g") 
 
     .attr("class", "node"); 
 

 
     //Adjusting the node sizes according to the children 
 
     nodeEnter.append("circle") 
 
     .style("display", function(d) { 
 
      return d.children ? "none" : ""; 
 
     }) 
 
     .attr("stroke", 'black') 
 
     .attr("r", function(d) { 
 
      var r = rand(6, 18); 
 
      return d._children ? d.size ? 14 : 18 : d.children ? 24 : r; 
 
     }); 
 

 
     nodeEnter.append("text") 
 
     .attr("dy", ".35em") 
 
     .text(function(d) { 
 
      return d.name; 
 
     }).style("display", function(d) { 
 
      return d.children ? "none" : ""; 
 
     }) 
 
     .style("font-size", function(d) { 
 
      return 10; 
 
     }); 
 
     node.select("circle") 
 
     .style("fill", color(colorIdx)); 
 
    } 
 

 
    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("transform", function(d) { 
 
     return "translate(" + d.x + "," + d.y + ")"; 
 
     }); 
 
    } 
 

 

 
    // Returns a list of all nodes under the root. 
 
    function flatten(root) { 
 
     var nodes = [], 
 
     i = 0; 
 

 
     function recurse(node) { 
 
     if (node.children) node.children.forEach(recurse); 
 
     if (!node.id) node.id = ++i; 
 
     nodes.push(node); 
 
     } 
 

 
     recurse(root); 
 
     return nodes; 
 
    } 
 

 
    })();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="main-container"></div>

+0

感谢,很多关于你的答案。有没有办法将力布局应用到更大的圆圈空间,所以它们的位置更接近和像图片一样更随机?谢谢! – Dmitry

+0

你为什么不为自己的大圈子计算一些随机位置?我认为这不会很难.. – Gilsha

+0

嗨@Gilsha,我可能会做到这一点,但我担心圈子可能互相重叠。我无法弄清楚如何将力量布局应用到更大的圈子中,以便他们可以像小团队那样行事,而“其他力量布局”则适用于较小的圈子。所以这对我来说很棘手 – Dmitry