Skip to content

Instantly share code, notes, and snippets.

@rphv
Last active April 27, 2016 10:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rphv/0d6c8f05b3afe882e166 to your computer and use it in GitHub Desktop.
Save rphv/0d6c8f05b3afe882e166 to your computer and use it in GitHub Desktop.
Draggable Circle Packing - D3.js
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>Draggable Circle Packing</title>
<style>
svg circle {
cursor: move;
stroke: #000;
stroke-width: 1.5px;
fill: #827d92;
}
.fixed {
fill: #f00;
}
button {
position: absolute;
top: 10px;
left: 10px;
}
</style>
</head>
<body>
<button onclick="reset()">Reset</button>
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 900;
var height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var nodes = d3.range(128).map(function () { return {radius: Math.random() * 16 + 8}; });
var nodesCopy = $.extend(true, [], nodes);
function dblclick(d) {
d3.select(this).classed("fixed", d.fixed = false);
}
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
function collide(node) {
var r = node.radius + 16;
var nx1 = node.x - r;
var nx2 = node.x + r;
var ny1 = node.y - r;
var ny2 = node.y + r;
return function (quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== node)) {
var x = node.x - quad.point.x;
var y = node.y - quad.point.y;
var l = Math.sqrt(x * x + y * y);
var npr = node.radius + quad.point.radius;
if (l < npr) {
l = (l - npr) / l * 0.5;
x *= l;
node.x -= x;
y *= l;
node.y -= y;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
}
function packup() {
var pack = d3.layout.pack()
.sort(null)
.size([width, height])
.padding(0)
.value(function (d) { return d.radius; });
svg.selectAll(".node")
.data(pack.nodes({"children": nodes})
.filter(function (d) { return !d.children; }))
.enter().append("circle")
.attr("r", function (d) { return d.radius; })
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
}
function forceup() {
var force = d3.layout.force()
.nodes(nodes)
.gravity(0.05)
.charge(0)
.size([width, height])
.start();
var drag = force.drag().on("dragstart", dragstart);
force.on("tick", function () {
var q = d3.geom.quadtree(nodes);
var i = 0;
var n = nodes.length;
while (++i < n) {
q.visit(collide(nodes[i]));
}
svg.selectAll("circle")
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
});
d3.selectAll("circle")
.on("dblclick", dblclick)
.call(drag);
}
function reset() {
svg.selectAll("*").remove();
nodes = $.extend(true, [], nodesCopy);
packup();
forceup();
}
packup();
forceup();
</script>
</body>
</html>
@nikhilkabbin
Copy link

Hi, Could you please give me an example of resizing the parent node on drag and drop of the children from one parent to different parent

http://codepen.io/MrHen/pen/GZQOPW, I am unable to resize of the bubble on drop of the bubble into other circles?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment