Public
Edited
May 20, 2022
2 stars
Insert cell
# 2D Gravity
Insert cell
<div style="display: flex; justify-content: center; align-items: center; margin: 20px;">
<svg></svg>
</div>
Insert cell
Could improve this animation by adding z-indexes and detecting when distances switches from increasing to decreasing to toggle them in front of / behind the center(s) of gravity
Insert cell
Could make this more fun by adding more centers of 2D gravity
- makeGravity would iterate over each particle, each gravity to update coordinates
Insert cell
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();
}
Insert cell
setTimeout(initGravity, 1000)
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more