A minimalist variation of Jonathan Corum’s interactive graphic on exoplanets discovered by NASA’s Kepler mission. This version lacks stars, labels, and more, but demonstrates the use of CSS3 for simple declarative animation of orbits.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
background: #222;
position: relative;
text-align: center;
}
.system {
display: inline-block;
position: relative;
vertical-align: middle;
}
.orbit {
fill: none;
stroke: #ccc;
stroke-dasharray: 2,3;
}
.planet {
position: absolute;
top: 0;
left: 0;
-moz-animation-name: rotate;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: linear;
-webkit-animation-name: rotate;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
animation-name: rotate;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.planet circle {
fill: url(#planet-gradient);
}
@-moz-keyframes rotate {
from { -moz-transform: rotateZ(0deg); }
to { -moz-transform: rotateZ(-360deg); }
}
@-webkit-keyframes rotate {
from { -webkit-transform: rotateZ(0deg); }
to { -webkit-transform: rotateZ(-360deg); }
}
@keyframes rotate {
from { transform: rotateZ(0deg); }
to { transform: rotateZ(-360deg); }
}
</style>
<svg style="position:absolute;width:0;height:0;">
<defs>
<radialGradient id="planet-gradient" gradientUnits="objectBoundingBox" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#aaa" stop-opacity="1"/>
<stop offset="100%" stop-color="#777" stop-opacity="1"/>
</radialGradient>
</defs>
</svg>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
// Scales for semimajor axis, planet radius, and planet period.
var x = d3.scale.linear().range([0, 400]),
r = d3.scale.linear().domain([4, 40]).range([4 * .5, 40 * .5]).clamp(true),
t = d3.scale.linear().range([0, 1]);
var padding = 16;
// Detect the appropriate vendor prefix.
var prefix = "-webkit-transform" in document.body.style ? "-webkit-"
: "-moz-transform" in document.body.style ? "-moz-"
: "";
d3.csv("planets.csv", type, function(error, planets) {
var systems = d3.nest()
.key(function(d) { return d.id; })
.entries(planets);
systems.forEach(function(s) {
s.values.forEach(function(p) { p.system = s; });
s.radius = d3.max(s.values, function(p) { return x(p.semimajor_axis) + r(p.planet_radius); }) + padding;
});
systems.sort(function(a, b) {
return a.radius - b.radius;
});
var system = d3.select("body").selectAll(".system")
.data(systems)
.enter().append("div")
.attr("class", "system")
.style("width", function(d) { return d.radius * 2 + "px"; })
.style("height", function(d) { return d.radius * 2 + "px"; });
system.append("svg")
.attr("class", "orbit")
.attr("width", function(d) { return d.radius * 2; })
.attr("height", function(d) { return d.radius * 2; })
.append("g")
.attr("transform", function(d) { return "translate(" + d.radius + "," + d.radius + ")"; })
.selectAll("circle")
.data(function(d) { return d.values; })
.enter().append("circle")
.attr("r", function(d) { return x(d.semimajor_axis); });
system.selectAll(".planet")
.data(function(d) { return d.values; })
.enter().append("svg")
.attr("class", "planet")
.attr("width", function(d) { return d.system.radius * 2; })
.attr("height", function(d) { return d.system.radius * 2; })
.style(prefix + "animation-duration", function(d) { return t(d.period) + "s"; })
.style(prefix + "transform-origin", function(d) { return d.system.radius + "px " + d.system.radius + "px"; })
.append("circle")
.attr("transform", function(d) { return "translate(" + d.system.radius + "," + d.system.radius + ")"; })
.attr("cx", function(d) { return x(d.semimajor_axis); })
.attr("r", function(d) { return r(d.planet_radius); });
});
function type(d) {
d.period = +d.period;
d.planet_radius = +d.planet_radius;
d.semimajor_axis = +d.semimajor_axis;
d.stellar_radius = +d.stellar_radius;
return d;
}
</script>
https://d3js.org/d3.v3.min.js