function earth_venus_anim() {
let w = width < 700 ? width : 700;
let h = w;
let div = d3
.create('div')
.style('width', `${w}px`)
.style('height', `${h + 30}px`);
let running = true;
let interval_id;
let controls = div
.append('div')
.style('width', `${300}px`)
.style('height', `${30}px`);
let start_stop_button = controls
.append('div')
.style('display', 'inline-block')
.append('button')
.on('click', function() {
if (running) {
running = false;
clearInterval(interval_id);
d3.select(this).html('start');
} else {
running = true;
start();
d3.select(this).html('stop');
}
})
.html('stop');
controls
.append('div')
.style('display', 'inline-block')
.append('button')
.on('click', setup)
.html('reset');
let container = div
.append('div')
.style('position', 'relative')
.style('width', `${w}px`)
.style('height', `${h}px`);
let pad = 10;
let canvas = container
.append('canvas')
.attr('width', w)
.attr('height', h)
.style('position', 'absolute')
.style('top', 0)
.style('left', 0);
let context = canvas.node().getContext('2d');
let svg = container
.append('svg')
.attr('width', w)
.attr('height', h)
.style('position', 'absolute')
.style('top', 0)
.style('left', 0);
let bb = 1;
let xmin = -bb;
let xmax = bb;
let ymin = -bb;
let ymax = bb;
let xScale = d3
.scaleLinear()
.domain([xmin, xmax])
.range([pad, w - pad]);
let yScale = d3
.scaleLinear()
.domain([ymin, ymax])
.range([h - pad, pad]);
let rScale = d3
.scaleLinear()
.domain([0, xmax - xmin])
.range([0, w - 2 * pad]);
let T, earth, venus, connect;
function setup() {
if (running) {
running = false;
clearInterval(interval_id);
start_stop_button.html('start');
}
context.clearRect(0, 0, w, h);
T = 0;
context.beginPath();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0, 1)";
context.moveTo(xScale(1), yScale(0));
context.arc(xScale(0), yScale(0), rScale(1), 0, 2 * Math.PI);
context.stroke();
context.closePath();
context.beginPath();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0, 1)";
context.moveTo(xScale(0) + oscale * rScale(vr), yScale(0));
context.ellipse(
xScale(0),
yScale(0),
oscale * rScale(vr),
rScale(vr),
0,
0,
2 * Math.PI
);
context.stroke();
context.closePath();
context.beginPath();
context.lineWidth = 1;
context.moveTo(xScale(1), yScale(0));
context.lineTo(xScale(vr), yScale(0));
context.strokeStyle = "rgba(0,0,0, 0.1)";
context.stroke();
context.closePath();
svg.selectAll('line').remove();
connect = svg
.append('line')
.style('stroke', 'black')
.style('stroke-width', '2');
svg.selectAll('circle').remove();
earth = svg
.append('circle')
.attr('id', 'earth')
.attr('cx', xScale(1))
.attr('cy', yScale(0))
.attr('r', rScale(0.025))
.attr('fill', 'blue');
venus = svg
.append('circle')
.attr('id', 'venus')
.attr('cx', xScale(0) + oscale * rScale(vr))
.attr('cy', yScale(0))
.attr('r', rScale(0.015))
.attr('fill', 'red');
svg
.append('circle')
.attr('cx', xScale(0))
.attr('cy', yScale(0))
.attr('r', rScale(0.1))
.attr('fill', function() {
if (math.evaluate(vspeed) == 1) {
return 'black';
} else {
return '#efef00';
}
})
.attr('stroke-width', 3)
.attr('stroke', function() {
if (math.evaluate(vspeed) == 1) {
return 'black';
} else {
return '#dd0';
}
});
}
function start() {
let t = T;
let s = math.evaluate(vspeed);
let step = Math.PI / 400;
running = true;
interval_id = setInterval(function() {
if (running) {
let ep = earth_position(t);
let vp = venus_position(s, t);
earth.attr('cx', xScale(ep[0])).attr('cy', yScale(ep[1]));
venus.attr('cx', xScale(vp[0])).attr('cy', yScale(vp[1]));
connect
.attr('x1', xScale(ep[0]))
.attr('y1', yScale(ep[1]))
.attr('x2', xScale(vp[0]))
.attr('y2', yScale(vp[1]));
context.beginPath();
context.lineWidth = 1;
context.strokeStyle = "rgba(0,0,0, 0.1)";
context.moveTo(xScale(ep[0]), yScale(ep[1]));
context.lineTo(xScale(vp[0]), yScale(vp[1]));
context.stroke();
context.closePath();
t = t + step;
T = t;
}
}, 20);
}
setup();
start();
start_stop_button.text('stop');
return div.node();
}