function initGravity() {
const svgWidth = 400,
svgHeight = 400,
halfWidth = svgWidth / 2,
halfHeight = svgHeight / 2,
particleIndex = 10,
randomColor = () =>
"#" + ((Math.random() * 0xffffff) << 0).toString(16).padStart(6, "0");
const dataset = {
gravity: { x: 0, y: 0, r: 60, fill: "black" },
particles: []
};
const svg = d3
.select("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.style("border", "1px solid black");
for (let z = 0; z < particleIndex; z++) {
dataset.particles.push({
x: Math.floor(Math.random() * svgWidth),
y: Math.floor(Math.random() * svgHeight),
fill: randomColor(),
r: 10,
velocity: {
x: Math.floor(Math.random() * 1 - 1),
y: Math.floor(Math.random() * 1 - 1)
}
});
}
function makeGravity() {
const { gravity } = dataset;
dataset.particles = dataset.particles.map((p) => {
const particle = Object.assign({}, p);
const distance =
Math.pow(particle.x - gravity.x, 2) +
Math.pow(particle.y - gravity.y, 2);
const f = 1 / Math.sqrt(distance);
particle.velocity.x += (particle.x - gravity.x) * f;
particle.velocity.y += (particle.y - gravity.y) * f;
particle.x -= particle.velocity.x;
particle.y -= particle.velocity.y;
return particle;
});
svg.selectAll("circle").remove();
svg
.selectAll("circle")
.data([dataset.gravity, ...dataset.particles])
.enter()
.append("circle")
.attr("cy", (d) => d.y + halfHeight)
.attr("cx", (d) => d.x + halfWidth)
.attr("r", (d) => d.r)
.attr("fill", (d) => d.fill);
setTimeout(makeGravity, 50);
}
makeGravity();
}