|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
.circle { |
|
fill-opacity: .5; |
|
} |
|
|
|
.ring { |
|
fill: none; |
|
stroke: #000; |
|
pointer-events: none; |
|
} |
|
|
|
.ring-inner { |
|
stroke-width: 5px; |
|
stroke-opacity: .25; |
|
} |
|
|
|
.moon { |
|
stroke-width: 1px; |
|
stroke: #444; |
|
fill: none; |
|
} |
|
|
|
.earth { |
|
stroke-width: 1px; |
|
stroke: blue; |
|
fill: none; |
|
} |
|
|
|
.vector { |
|
stroke-width: 2px; |
|
fill: none; |
|
} |
|
|
|
</style> |
|
<svg width="960" height="500"></svg> |
|
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script> |
|
var sun_dist = 149.6e9; |
|
var moon_dist = 370.3e6; |
|
var sun_r = 696.342e6 |
|
var earth_r = 6.371e6; |
|
var moon_r = 1.737e6; |
|
var sun_mass = 1.989e30; |
|
var earth_mass = 5.972e24; |
|
var moon_mass = 7.36e22; |
|
|
|
var c1 = {x: 480, y: 250, r: sun_r/3e7, color: "orange"}, |
|
c2 = {x: 600, y: 100, r: earth_r/3e7, color: "blue"}, |
|
c3 = {x: 600, y: 300, r: moon_r/3e7, color: "#444"}; |
|
|
|
var a_scale = 0.5; |
|
|
|
var v1 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "orange"}; |
|
v2 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "blue"}; |
|
v3 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "#444"}; |
|
|
|
function update_pos(t) |
|
{ |
|
c2.x = c1.x + sun_dist/1e9 * Math.cos(t); |
|
c2.y = c1.y - sun_dist/1e9 * Math.sin(t); |
|
c3.x = c2.x + moon_dist/1e9 * Math.cos(t * 13); |
|
c3.y = c2.y - moon_dist/1e9 * Math.sin(t * 13); |
|
var dx = c1.x - c3.x; |
|
var dy = c1.y - c3.y; |
|
var len = Math.sqrt(dx*dx + dy*dy); |
|
v1.x1 = c3.x; |
|
v1.y1 = c3.y; |
|
v1.x2 = v1.x1 + dx*sun_mass/1e25/(len*len*len); |
|
v1.y2 = v1.y1 + dy*sun_mass/1e25/(len*len*len); |
|
|
|
dx = c2.x - c3.x; |
|
dy = c2.y - c3.y; |
|
len = Math.sqrt(dx*dx + dy*dy); |
|
v2.x1 = c3.x; |
|
v2.y1 = c3.y; |
|
v2.x2 = v2.x1 + dx*earth_mass/1e25/(len*len*len); |
|
v2.y2 = v2.y1 + dy*earth_mass/1e25/(len*len*len); |
|
|
|
v3.x1 = c3.x; |
|
v3.y1 = c3.y; |
|
v3.x2 = v3.x1 + v1.x2 - v1.x1 + v2.x2 - v2.x1; |
|
v3.y2 = v3.y1 + v1.y2 - v1.y1 + v2.y2 - v2.y1; |
|
} |
|
|
|
var color = d3.scale.category10(); |
|
|
|
var svg = d3.select("svg"); |
|
|
|
svg.style("pointer-events", "all"); |
|
|
|
svg = svg.append("g") |
|
.call(d3.behavior.zoom().scaleExtent([1, 40]).on("zoom", zoom)) |
|
.append("g"); |
|
|
|
var earth = svg.append("circle").attr("class", "earth") |
|
.attr("r", sun_dist/1e9) |
|
.attr("cx", c1.x) |
|
.attr("cy", c1.y); |
|
|
|
svg.append("path").attr("class", "moon") |
|
.attr("d", function () { |
|
var path = ["M0,0"]; |
|
for (var i=0; i < 201; ++i) { |
|
var t1 = i*2*Math.PI/200; |
|
update_pos(t1); |
|
path.push((i?"L":"M"), c3.x, ",", c3.y); |
|
} |
|
return path.join(""); |
|
}); |
|
|
|
var vectors = svg.selectAll(".vector") |
|
.data([v1, v2, v3]).enter() |
|
.append("path") |
|
.attr("class", "vector") |
|
.style("stroke", function (d) { return d.color; }); |
|
|
|
function zoom() { |
|
svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); |
|
svg.select("path").style("stroke-width", 1/d3.event.scale); |
|
earth.style("stroke-width", 1/d3.event.scale); |
|
vectors.style("stroke-width", 2/d3.event.scale); |
|
a_scale = Math.min(5/d3.event.scale, 0.5); |
|
} |
|
|
|
var circles = svg.selectAll(".circle") |
|
.data([c1, c2, c3]); |
|
var circle = circles |
|
.enter().append("g") |
|
.attr("class", "circle") |
|
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) |
|
.style("fill", function(d) { return d.color; }); |
|
|
|
circle.append("circle") |
|
.attr("r", function(d) { return d.r; }); |
|
|
|
function vectorP(v) |
|
{ |
|
var path = ["M", v.x1, ",", v.y1]; |
|
path.push("L", v.x2, ",", v.y2); |
|
var dx = v.x2 - v.x1; |
|
var dy = v.y2 - v.y1; |
|
var len = dx*dx + dy*dy; |
|
if (Math.abs(len) > 1e-7) |
|
{ |
|
len = Math.sqrt(len); |
|
dx /= len; |
|
dy /= len; |
|
path.push("L", v.x2 - dy * a_scale - dx * a_scale, ",", v.y2 + dx * a_scale - dy * a_scale); |
|
path.push("L", v.x2 + dy * a_scale - dx * a_scale, ",", v.y2 - dx * a_scale - dy * a_scale); |
|
path.push("L", v.x2, ",", v.y2); |
|
path.push("Z"); |
|
} |
|
return path.join(""); |
|
} |
|
|
|
function update() { |
|
vectors.each(function(d) { |
|
d3.select(this).attr("d", vectorP(d)); |
|
}); |
|
} |
|
|
|
var start = Date.now(); |
|
|
|
d3.timer( function (){ |
|
var t1 = (Date.now() - start)/20000; |
|
update_pos(t1); |
|
circles.each(function (d) { |
|
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")"); |
|
}); |
|
update(); |
|
}); |
|
|
|
</script> |