Orbiting planets and moons with D3.js, inspired by Jan van der Laan's Planetarium. Orbital speeds are roughly scaled relative to one another.
Orbits
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
width: 960px; | |
height: 500px; | |
position: relative; | |
} | |
#sun { | |
stroke: #666; | |
fill: #666; | |
} | |
.orbit { | |
stroke: #ccc; | |
fill: transparent; | |
} | |
.planet { | |
stroke: #666; | |
fill: #fff; | |
} | |
.moon { | |
stroke: #ccc; | |
fill: #fff; | |
} | |
</style> | |
</head> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
// establish variables | |
var w = 960; | |
var h = 500; | |
var x = (w/2) - 250; | |
var y = (h/2) - 150; | |
var t0 = new Date().setHours(0,0,0,0); | |
var delta = (Date.now() - t0); | |
// planets and moons | |
var planets = [ | |
{ R: 23, r: 1, speed: -1.60, phi0: 35, moons: [ // mercury | |
]}, | |
{ R: 45, r: 2, speed: -1.17, phi0: 185, moons: [ // venus | |
]}, | |
{ R: 87, r: 2, speed: -1.00, phi0: 135, moons: [ // earth | |
{ R: 10, r: 1, speed: -9.00, phi0: 15 } // the moon | |
]}, | |
{ R: 140, r: 1, speed: -0.80, phi0: 235, moons: [ // mars | |
{ R: 6, r: 0.5, speed: -3.80, phi0: 15 }, // phobos | |
{ R: 9, r: 0.5, speed: -2.80, phi0: 115 } // deimos | |
]}, | |
{ R: 290, r: 22, speed: -0.43, phi0: 135, moons: [ // jupiter | |
{ R: 30, r: 2, speed: -7.70, phi0: 25 }, // io | |
{ R: 36, r: 1, speed: -2.45, phi0: 95 }, // europa | |
{ R: 49, r: 3, speed: -1.10, phi0: 125 }, // ganymede | |
{ R: 79, r: 2, speed: -0.50, phi0: 315 } // callisto | |
]}, | |
{ R: 583, r: 18, speed: -0.32, phi0: 260, moons: [ // saturn | |
{ R: 28, r: 1, speed: -4.10, phi0: 120 }, // mimas | |
{ R: 33, r: 1, speed: -3.90, phi0: 20 }, // enceladus | |
{ R: 38, r: 1, speed: -3.60, phi0: 0 }, // tethys | |
{ R: 44, r: 1, speed: -3.20, phi0: 100 }, // dione | |
{ R: 58, r: 2, speed: -2.90, phi0: 300 }, // rhea | |
{ R: 98, r: 5, speed: -1.30, phi0: 180 }, // titan | |
{ R: 188, r: 2, speed: -0.10, phi0: 10 } // lapetus | |
]} | |
]; | |
// insert svg element | |
var svg = d3.select('body').insert("svg") | |
.attr("width", w) | |
.attr("height", h); | |
// sun | |
svg.append("circle") | |
.attr("r", 10) | |
.attr("cx", x) | |
.attr("cy", y) | |
.attr("id", "sun"); | |
// planet group | |
var container = svg.append("g") | |
.attr("id", "orbit_container") | |
.attr("transform", "translate(" + x + "," + y + ")"); | |
// draw planets and moon clusters | |
container.selectAll("g.planet").data(planets).enter().append("g") | |
.attr("class", "planet_cluster").each(function(d, i) { | |
d3.select(this).append("circle").attr("class", "orbit") | |
.attr("r", d.R); | |
d3.select(this).append("circle").attr("r", d.r).attr("cx",d.R) | |
.attr("cy", 0).attr("class", "planet"); | |
d3.select(this).append("g").attr("transform", "translate(" + d.R + ",0)") | |
.selectAll("g.moon").data(d.moons).enter().append("g") | |
.attr("class", "moon_cluster").each(function(d, i) { | |
d3.select(this).append("circle").attr("class", "orbit") | |
.attr("r", d.R); | |
d3.select(this).append("circle").attr("r", d.r).attr("cx",d.R) | |
.attr("cy", 0).attr("class", "moon"); | |
}) | |
.attr("transform", function(d) { | |
return "rotate(" + (d.phi0 + (delta * (d.speed/100))) + ")"; | |
}); | |
}) | |
.attr("transform", function(d) { | |
return "rotate(" + (d.phi0 + (delta * (d.speed/100))) + ")"; | |
}); | |
// throttled rotaiton animations | |
setInterval(function(){ | |
var delta = (Date.now() - t0); | |
svg.selectAll(".planet_cluster, .moon_cluster").attr("transform", function(d) { | |
return "rotate(" + (d.phi0 + (delta * (d.speed/100))) + ")"; | |
}); | |
}, 40); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment