Skip to content

Instantly share code, notes, and snippets.

@MichaelCurrie
Created November 4, 2016 04:21
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 MichaelCurrie/4b645e70e8bf324a0d0e8216f56fdb32 to your computer and use it in GitHub Desktop.
Save MichaelCurrie/4b645e70e8bf324a0d0e8216f56fdb32 to your computer and use it in GitHub Desktop.
Splitting bubbles using d3.js v4
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.button {
min-width: 130px;
padding: 4px 5px;
cursor: pointer;
text-align: center;
font-size: 13px;
border: 1px solid #e0e0e0;
text-decoration: none;
}
.button.active {
background: #000;
color: #fff;
}
.focusLine {
fill: none;
stroke: steelblue;
stroke-width: 0.5px;
}
</style>
<div id="toolbar">
<a href="#" class="button active" id="split_bubbles">Split the Bubbles</a>
</div>
<div id="vis"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
/* Adapted from Mike Bostock: https://bl.ocks.org/mbostock/31ce330646fa8bcb7289ff3b97aab3f5 */
var width = 960, height = 960;
var num_nodes = 200;
// Initialize some "nodes" with random radii
var nodes = d3.range(num_nodes).map(function(i) {
return {
r: Math.random() * 14 + 4,
tx: 0, ty: 0, // relative to the translated center
inGroup1: Math.random() >= 0.5 // random boolean
};
});
var width = 960, height = 960;
var center = {x: width/2, y: height/2};
var DAMPER = 0.102 * 1.1;
var simulation = d3.forceSimulation(nodes)
//.force("center", d3.forceCenter([10,100]))
.velocityDecay(0.1)
.force("collide", d3.forceCollide().radius(function(d) { return d.r + 0.5; }).iterations(2))
.on("tick", ticked);
simulation
.force("x", d3.forceX(0).strength(0.006))
.force("y", d3.forceY(0).strength(0.006));
// Create our SVG context
var svg = d3.select('#vis')
.append('svg')
.attr('width', width)
.attr('height', height);
// Show our center
var focus = svg.append('g');//.style('display', 'none');
focus.append('line')
.attr('id', 'focusLineX')
.attr('x1', center.x).attr('y1', 0)
.attr('x2', center.x).attr('y2', height)
.attr('class', 'focusLine');
focus.append('line')
.attr('id', 'focusLineY')
.attr('class', 'focusLine')
.attr('x1', 0).attr('y1', center.y)
.attr('x2', width).attr('y2', center.y);
// Add a bubble
svg.selectAll('.bubble')
.data(nodes, function (d) { return d.id; })
.enter().append('circle')
.classed('bubble', true)
.attr('r', function (d) { return d.r; })
.attr('fill', function (d) { if(d.inGroup1) { return '#ddd'; } else { return 'red' }})
.attr('stroke', '#333');
var bubbles = d3.selectAll('.bubble');
bubbles.attr("transform", "translate("+width/2+","+height/2+")");
function ticked() {
//bubbles.each(modifyNodePosition(this.alpha()))
bubbles.each(function (node) {})
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
/*function modifyNodePosition(alpha) {
return function (node) {
node.x = node.x + (node.tx - node.x) * alpha * DAMPER;
node.y = node.y + (node.ty - node.y) * alpha * DAMPER;
};
}*/
d3.select('#toolbar')
.selectAll('.button')
.on('click', function () {
// Get the id of the button
var buttonId = d3.select(this).attr('id');
if (buttonId = "split_bubbles"){
function fX (d) {
var targetX;
if (d.inGroup1) {
targetX = -200;
} else {
targetX = 200;
}
return targetX;
}
simulation
.force("x", d3.forceX(fX).strength(0.006))
.force("y", d3.forceY(0).strength(0.006));
simulation.alphaTarget(1).restart();
}
});
</script>
@MichaelCurrie
Copy link
Author

It should start like this:

image

Pressing the button should change it to this:

image

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