D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
GitNoise
Full window
Github gist
Split circles animation
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v5.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } .dot { fill: rgb(255, 0, 0); } .center { fill: rgb(0, 0, 255, 0.5); stroke: rgba(0, 0, 255, 1); r: 10; } </style> </head> <body> <script> const width = 500, height = 500; const centerCoord = [width/2, height/2] var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) const drawDots = function(data, duration) { return new Promise(function(resolve, reject) { var dots = svg.selectAll('.dot') .data(data, d => d.id) const transition = d3.transition() .duration(duration) .end().then(resolve); dots .transition(transition) .duration(duration) .ease(d3.easeBack) .attr('cx', d => d.x) .attr('cy', d => d.y) .attr('r', d => d.r) dots.enter() .append('circle') .classed('dot', true) .attr('r', d => d.r) .attr('cx', d => d.x) .attr('cy', d => d.y) dots.exit() .remove(); }); } const dataSimulation = new Promise(function(resolve, reject) { const noOfDots = 100; const data = d3.range(noOfDots).map((d, i) => ( { id: `dot${i}`, x: centerCoord[1], y: centerCoord[0], r: 5 } )); const steps = 300; const force = d3.forceSimulation() .nodes(data) .force('collision', d3.forceCollide().radius(7).strength(1/steps * 10)) .alphaDecay(1 - Math.pow(0.001, 1 / (steps / 2))) .on('end', () => resolve(data)) }); async function myMain() { /****************** DATA *************/ const dataInitial = [ {id: 'dot_1', y: height*.2, x: width*.4, r: 20}, {id: 'dot_2', y: height*.3, x: width*.6, r: 30}, {id: 'dot_3', y: height*.4, x: width*.2, r: 30}, ]; const dataCentered = dataInitial.map(d => ( { id: d.id, y: centerCoord[0], x: centerCoord[1], r: 5, } )); const dataSimulated = await dataSimulation; const dataSimualtedCentered = dataSimulated.map(d => ({ id: d.id, y: centerCoord[0], x: centerCoord[1], r: 5, })); const splitKeep = dataSimulated.slice(0, Math.round(dataSimulated.length * 0.25)); let splitRemove = dataSimulated.slice(splitKeep.length) splitRemove = splitRemove.map(d => ({ id: d.id, x: width * 2, y: d.y, r: d.r, })); const dataSimulatedSplit = splitKeep.concat(splitRemove); // create animation steps const animationSteps = [ dataInitial, dataCentered, dataSimulated, dataSimulatedSplit, dataSimualtedCentered, ]; /******* Draw dots ***********/ // draw large dots await drawDots(animationSteps[0], 1000); while(true) { // center large dots await drawDots(animationSteps[1], 2000); await drawDots(animationSteps[4], 0); // create small dots and remove large dots await drawDots(animationSteps[2], 2000); // split small dots await drawDots(animationSteps[3], 2000); // merge small dots await drawDots(animationSteps[2], 2000); // center small dots await drawDots(animationSteps[4], 2000); // remove small dots and create large dots await drawDots(animationSteps[1], 0); // move large dots to intial position await drawDots(animationSteps[0], 1000); } } myMain(); </script> </body>
https://d3js.org/d3.v5.min.js