Simulation of multiple particles orbitting around each other in a hierarchical system (e.g. sun > planet > moon).
Uses D3's force plugin forceMagnetic to connect particles to their moving gravitational centers via magnetic/electrostatic links. These magnetic attraction forces simulate the mechanics of gravity. Each link holds its own gravitational constant to exaggerate the amplitude and velocity of the orbits relative to each other, which would be otherwise impossible in a system with a single constant.
Compare with the forceLink version.
xxxxxxxxxx
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.7.0/d3.min.js"></script>
<script src="//unpkg.com/d3-force-magnetic"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<svg id="canvas">
<g id="trails"></g>
<g id="bodies"></g>
</svg>
<script>
const width = window.innerWidth, height = window.innerHeight;
const au = Math.min(width, height) / 4; // Astronomical unit
const gravity = 0.3, // Regulates mechanics speed
bodies = [
{ id: 'sun', mass: 1000, r: 20 },
{ id: 'planet', mass: 10, r: 8, x: 0, y: -au, vx: Math.sqrt(1000 * gravity / au), vy: 0 }, // vx set to orbital speed: sqrt(GM/d)
{ id: 'moon', mass: 0, r: 2, x: 0, y: -au * 1.5, vx: 1.1 * Math.sqrt(10 * (gravity * 500) / (au * 0.5)), vy: 0 }
],
links = [
{ source: 'planet', target: 'sun', attraction: gravity },
{ source: 'moon', target: 'planet', attraction: gravity * 500 } // Higher attraction = more revolutions
];
d3.forceSimulation()
.alphaDecay(0)
.velocityDecay(0)
.nodes(bodies)
.force("gravitate-around", d3.forceMagnetic()
.id(d => d.id)
.charge(node => node.mass)
.strength(link => link.attraction || 0.1)
.links(links)
)
.on("tick", ticked);
// Add orbit trails
d3.timer(() => {
d3.selectAll('g.trail')
.append('circle')
.attr('r', 1.5)
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.transition().duration(5000)
.style('opacity', 0)
.remove();
});
// Size canvas
d3.select('#canvas')
.attr('width', width)
.attr('height', height)
.attr('viewBox', `${-width/2} ${-height/2} ${width} ${height}`);
//
function ticked() {
var body = d3.select('#bodies').selectAll('.body')
.data(bodies);
body.exit().remove();
body.merge(
body.enter().append('circle')
.attr('class', 'body')
.attr('id', d => d.id)
.attr('r', d => d.r)
)
.attr('cx', d => d.x)
.attr('cy', d => d.y);
// Add trail elements
var trails = d3.select('#trails').selectAll('.trail')
.data(bodies);
trails.exit().remove();
trails.enter().append('g').attr('class', 'trail');
}
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/4.7.0/d3.min.js
https://unpkg.com/d3-force-magnetic