var data = [ { name: '01', group: 'one', value: 55 }, { name: '02', group: 'two', value: 21 }, { name: '03', group: 'two', value: 55 }, { name: '04', group: 'one', value: 89 }, { name: '05', group: 'one', value: 144 }, { name: '06', group: 'two', value: 144 }, { name: '07', group: 'one', value: 233 }, { name: '08', group: 'one', value: 377 }, { name: '09', group: 'two', value: 89 } ] var svg = d3.select('svg') var width = +svg.attr('width') var height = +svg.attr('height') var g = svg.select('g#vis') var sqrtScale = d3.scaleSqrt() .domain([1, 100]) .range([5, 40]) // when split move the items in group 'one' anchor at 200px // and the remaining (group 'two') to anchor at 700px var forceSplit = d3.forceX(function (d) { return (d.group === 'one') ? 200 : 700; }) .strength(0.05) // when using join bring all circles to the center of width var forceJoin = d3.forceX(function (d) { return width / 2; }) .strength(0.05) // y is set to center of height for everything var forceY = d3.forceY(height / 2) .strength(0.05) // https://github.com/d3/d3-force#forceSimulation var simulation = d3.forceSimulation() .force('x', forceJoin) .force('y', forceY) // spring out from the center instead of entering in from the top left .force('center', d3.forceCenter(width / 2, height / 2)) // stop the circles overlapping by passing in their size .force('collide', d3.forceCollide(function (d) { return sqrtScale(d.value) + 2; })) function render(data) { var circles = g.selectAll('.node') .data(data) .enter().append('circle') .attr('class', 'node') .attr('r', function (d) { return sqrtScale(d.value); }) .attr('fill', function (d) { return (d.group == 'one') ? '#7AC143' : '#FDBB30'; }) .on('click', function(d) { // example to show click events on circles d3.select('#clickData').text(("name: " + (d.name) + " value: \n " + (d.value))) }) simulation.nodes(data) .on('tick', ticked) function ticked() { circles .attr('cx', function (d) { return d.x; }) .attr('cy', function (d) { return d.y; }) } // events d3.select('#split').on('click', function() { console.log('split') simulation .force('x', forceSplit) // smooth out transitions to eliminate jitter .alphaTarget(0.3) // “reheat” the simulation during interaction // https://github.com/d3/d3-force#simulation_restart .restart() }) d3.select('#join').on('click', function() { console.log('join') simulation .force('x', forceJoin) .alphaTarget(0.1) .restart() }) } render(data)