Force Layout inside Force Layout
by Nivaldo
JavaScript
var svg = d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300);
////////////////////////
// outer force layout
var outerData = [{"id":"A"}, {"id":"B"}];
var outerLayout = d3.layout.force()
.size([300,300])
.charge(-4000)
.gravity(0.85)
.links([])
.nodes(outerData)
.on("tick", outerTick)
.start();
var outerNodes = svg.selectAll("g.outer")
.data(outerData, function (d) {return d.id;})
.enter()
.append("g")
.attr("class", "outer")
.attr("id", function (d) {return d.id;})
.call(outerLayout.drag());
outerNodes
.append("circle")
.style("fill", "pink")
.style("stroke", "blue")
.attr("r", 40);
////////////////////////
// inner force layouts
var innerAdata = [{"id":"A1"}, {"id":"A2"}];
var innerAlayout = d3.layout.force()
.size([40,40])
.charge(-600)
.gravity(0.75)
.links([])
.nodes(innerAdata)
.on("tick", innerAtick)
.start();
var aNode = svg.select("g.outer#A");
var innerAnodes = aNode.selectAll("g.inner")
.data(innerAdata, function (d) {return d.id;})
.enter()
.append("g")
.attr("class", "inner")
.attr("id", function (d) {return d.id;})
.call(innerAlayout.drag()
.on("dragstart", function(){
d3.event.sourceEvent.stopPropagation();
})
);
innerAnodes
.append("circle")
.style("fill", "orange")
.style("stroke", "blue")
.attr("r", 6);
///////
var innerBdata = [{"id":"B1"}, {"id":"B2"}];
var innerBlayout = d3.layout.force()
.size([40,40])
.charge(-600)
.gravity(0.75)
.links([])
.nodes(innerBdata)
.on("tick", innerBtick)
.start();
var bNode = svg.select("g.outer#B");
var innerBnodes = bNode.selectAll("g.inner")
.data(innerBdata, function (d) {return d.id;})
.enter()
.append("g")
.attr("class", "inner")
.attr("id", function (d) {return d.id;})
.call(innerBlayout.drag()
.on("dragstart", function(){
d3.event.sourceEvent.stopPropagation();
})
...