I am creating an inner solar sytem model from the percpective of Earth for creating astology birthcharts references. I am able to draw an optical axis line for the Earth - Sun axis, and the Earth - Moon axis but I can not for the life of me figure the trigonometry for the remaining inner planets. Here is a working pen. https://codepen.io/pjdroopypants/pen/wvEKeOm
window.onload = function(){
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
cw = canvas.width,
ch = canvas.height,
time = 1;
function circle(radius,color,x,y){
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(x,y,radius,0,2*Math.PI,true);
ctx.fill();
ctx.closePath();
}
function line(color,ax,ay,bx,by){
ctx.beginPath();
ctx.moveTo(ax*2,ay);
ctx.lineTo(bx+0.5,by+0.5);
ctx.strokeStyle = color;
ctx.stroke();
ctx.closePath();
}
var sunDegree = Math.floor(Math.random() * 359) + 1; //temporary, will use function from live planetary data
var merDegree = Math.floor(Math.random() * 359) + 1; //temporary, will use function from live planetary data
var venDegree = Math.floor(Math.random() * 359) + 1; //temporary, will use function from live planetary data
var marDegree = Math.floor(Math.random() * 359) + 1; //temporary, will use function from live planetary data
var mooDegree = Math.floor(Math.random() * 359) + 1; //temporary, will use function from live planetary data
var interval = 570.0930061551268;
function animate(){
ctx.save();
ctx.clearRect(0, 0, 1100, 1100);
ctx.translate(cw/2,ch/2);
//Earth
ctx.rotate(-(time / interval)+ Math.PI);
circle(15,"blue",0,0);
ctx.translate(480,0);
line("blue",-240,0,0,0);
ctx.translate(-480,0);
ctx.rotate((time / interval)+ Math.PI);
//Moon
var moontime = (time / (interval / 13.36996336996337)+mooDegree);
ctx.rotate(-moontime);
ctx.translate(23,0);
circle(3,"black",0,0);
ctx.translate(457,0);
line("#6a6a6a",-230,0,0,0);
ctx.translate(-480,0);
ctx.rotate(moontime);
//Sun
var suntime = time / interval;
ctx.rotate(-suntime);
ctx.translate(120,0);
circle(15,"yellow",0,0);
ctx.translate(360,0);
line("yellow",-182,0,0,0);
ctx.translate(-360,0);
ctx.rotate(suntime);
//Mercury
var mertime = (time / (interval / 4.150568181818182))+merDegree;
ctx.rotate(-(time / (interval / 4.150568181818182))+merDegree-suntime);
ctx.translate(40,0);
circle(15,"#898989",0,0);
ctx.translate(-40,0);
ctx.rotate((time / (interval / 4.150568181818182))+merDegree+suntime);
//Venus
ctx.rotate(-(time / (interval / 1.625500667556742))+venDegree-suntime);
ctx.translate(80,0);
circle(15,"#b9955b",0,0);
ctx.translate(-80,0);
ctx.rotate((time / (interval / 1.625500667556742))+venDegree);
//Mars
ctx.rotate(-(time / (interval / 0.5316593886462882))+marDegree);
ctx.translate(160,0);
circle(15,"#9f5e13",0,0);
ctx.translate(-160,0);
ctx.rotate((time / (interval / 0.5316593886462882))+marDegree);
ctx.restore();
time++;
window.requestAnimationFrame(animate);
}
window.requestAnimationFrame(animate);
}
I attempted to reverse rotate each animation iteration by subtracting the suns rotating angle but that just makes the axis line horizontal and not back to center.
Your code is a mess
You need to encapsulate the various parts so you can work with them individually.
The example below defines planets using a factory pattern to create planets as objects.
Each planet gets orbital ang, rate, and distance from the planet they orbit. Eg Mercury, Venus, Earth, Mars all orbit the Sun, and the Moon orbits the Earth.
Planets are created in orbital order. IE can not create planet before you create the planet it orbits.
On each animation frame each planet's position is calculated relative to the planet it orbits in the same order as they were created.
Before rendering the planet we want to center the view on a selected planet (in this case the Earth). The centered planets position is used to create a global matrix that will move all planets to the correct position.
Then when drawing each planet we multiply the global matrix by the planet's matrix ctx.setTransform(...globalMat); ctx.transform(this.cos, this.sin, -this.sin, this.cos, this.x, this.y);
and draw the result
requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d");
const TAU = Math.PI * 2;
const centerOnPlanetName = "Earth"; // Planet name to center view on
const globalMatrix = [1,0,0,1,0,0]; // holds position of planet to track
const solSystem = {}; // holds planets by name
const planets = []; // holds planets in order of created
const planetCommon = { // common properties of planets
x: 0, y: 0, cos: 1, sin: 0,
update(time) {
this.ang = this.startAng + this.orbitalSpeed * time;
this.cos = Math.cos(this.ang);
this.sin = Math.sin(this.ang);
if (this.orbits) { // Check if orbiting something
this.x = this.orbits.x + this.cos * this.dist;
this.y = this.orbits.y + this.sin * this.dist;
}
},
draw(ctx, globalMat) {
ctx.setTransform(...globalMat);
ctx.transform(this.cos, this.sin, -this.sin, this.cos, this.x, this.y);
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, TAU);
ctx.fill();
if (this.dirTo !== undefined) {
ctx.beginPath();
const ax = Math.cos(this.dirTo);
const ay = Math.sin(this.dirTo);
ctx.lineTo(ax * this.radius * 1.5, ay * this.radius * 1.5);
ctx.lineTo(ax * this.distTo, ay * this.distTo);
ctx.stroke();
}
},
directionTo(planet) {
if (planet !== this) {
this.dirTo = Math.atan2(planet.y - this.y, planet.x - this.x) - this.ang;
this.distTo = Math.hypot(planet.y - this.y, planet.x - this.x);
} else {
this.dirTo = undefined;
}
}
};
const planet = (name, orbitsName, dist, orbitalSpeed, startAng, radius, color) => {
planets.push(solSystem[name] = {
orbits: solSystem[orbitsName], // Set planet new planet orbits
dist, // dist from orbiting body
orbitalSpeed, // in radians per time unit
startAng, // starting angle in radians
radius,
color,
...planetCommon,
});
};
planet("Sun", undefined, 0, 0.8, - Math.PI, 20, "yellow");
planet("Mercury", "Sun", 45, 2, 0, 6, "#888");
planet("Venus", "Sun", 70, 1.2, 0, 15, "#CC8");
planet("Earth", "Sun", 120, 0.8, 0, 16, "#39B");
planet("Mars", "Sun", 175, 0.4, 0, 10, "#B43");
planet("Moon", "Earth", 30, 5, 0, 3, "#444");
function centerOn(cx, cy, planet) {
globalMatrix[4] = cx - planet.x;
globalMatrix[5] = cy - planet.y;
}
function mainLoop(time) {
time /= 1000;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
planets.forEach(planet => planet.update(time));
planets.forEach(planet => planet.directionTo(solSystem[centerOnPlanetName]));
centerOn(ctx.canvas.width * 0.5, ctx.canvas.height * 0.5, solSystem[centerOnPlanetName]);
planets.forEach(planet => planet.draw(ctx, globalMatrix));
requestAnimationFrame(mainLoop);
}
canvas {
border: 1px solid black;
}
<canvas id="canvas" width="600" height="600"></canvas>