|
<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> |