sketch using d3-force to split and join nodes via buttons
to help break this up, some sketches that show:
and this example shows user interaction to split and join via events
| 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) |
sketch using d3-force to split and join nodes via buttons
to help break this up, some sketches that show:
and this example shows user interaction to split and join via events
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <style> | |
| body{ | |
| font-family: Consolas, monaco, monospace; | |
| position: relative; | |
| padding: 20px; | |
| color: #FDBB30; | |
| background: #130C0E; | |
| } | |
| button { | |
| font-size: 18px; | |
| background: #130C0E; | |
| color: #7AC143; | |
| border: none; | |
| outline:none; | |
| padding: 4px 8px; | |
| margin-right: 10px; | |
| letter-spacing: 5px; | |
| } | |
| button:hover { | |
| background: #7AC143; | |
| color: #130C0E; | |
| } | |
| circle:hover { | |
| opacity: 0.8; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <button id='join'>JOIN</button> | |
| <button id='split'>SPLIT</button> | |
| </header> | |
| <svg width="960" height="400"> | |
| <g id="vis" transform="translate(10, 10)"></g> | |
| </svg> | |
| <footer> | |
| <span id="clickData"></span> | |
| </footer> | |
| <script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script> | |
| <!-- d3 code --> | |
| <script src=".script-compiled.js" charset="utf-8"></script> | |
| </body> | |
| </html> | |
| const 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 } | |
| ] | |
| const svg = d3.select('svg') | |
| const width = +svg.attr('width') | |
| const height = +svg.attr('height') | |
| const g = svg.select('g#vis') | |
| const 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 | |
| const forceSplit = d3.forceX(d => (d.group === 'one') ? 200 : 700) | |
| .strength(0.05) | |
| // when using join bring all circles to the center of width | |
| const forceJoin = d3.forceX(d => width / 2) | |
| .strength(0.05) | |
| // y is set to center of height for everything | |
| const forceY = d3.forceY(height / 2) | |
| .strength(0.05) | |
| // https://github.com/d3/d3-force#forceSimulation | |
| const 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(d => sqrtScale(d.value) + 2)) | |
| function render(data) { | |
| const circles = g.selectAll('.node') | |
| .data(data) | |
| .enter().append('circle') | |
| .attr('class', 'node') | |
| .attr('r', d => sqrtScale(d.value)) | |
| .attr('fill', d => (d.group == 'one') ? '#7AC143' : '#FDBB30') | |
| .on('click', function(d) { | |
| // example to show click events on circles | |
| d3.select('#clickData').text(`name: ${d.name} value: | |
| ${d.value}`) | |
| }) | |
| simulation.nodes(data) | |
| .on('tick', ticked) | |
| function ticked() { | |
| circles | |
| .attr('cx', d => d.x) | |
| .attr('cy', d => 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) |