Skip to content

Instantly share code, notes, and snippets.

@GitNoise
Last active September 2, 2019 08:15
Show Gist options
  • Save GitNoise/9315f081db45ddb9cd017d282ba11307 to your computer and use it in GitHub Desktop.
Save GitNoise/9315f081db45ddb9cd017d282ba11307 to your computer and use it in GitHub Desktop.
Split circles animation
license: mit
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment