<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
background-color: black;
font-family: sans-serif;
}

#solar-system {
position: relative;
width: 500px;
height: 500px;
margin: 50px auto;
perspective: 500px;
cursor: grab;
}

#solar-system:active {
cursor: grabbing;
}

#solar-system:hover {
cursor: grab;
}

#sun {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 279px;
height: 279px;
border-radius: 50%;
background-color: yellow;
}

.planet {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation-timing-function: linear;
opacity: 0.8;
}

#mercury {
animation: orbit-mercury 88d linear infinite;
background-color: #ff0000;
transform: translateX(-28px) translateY(10px) translateZ(-10px);
width: 1.8px;
height: 1.8px;
}

#venus {
animation: orbit-venus 224.7d linear infinite;
background-color: #ff6600;
transform: translateX(-41px) translateY(20px) translateZ(-20px);
width: 4.5px;
height: 4.5px;
}

#earth {
animation: orbit-earth 365.25d linear infinite;
background-color: #3366cc;
transform: translateX(-57px) translateY(30px) translateZ(-30px);
width: 4.8px;
height: 4.8px;
}

input[type=range], label[for=time-factor] {
display: inline-block;
vertical-align: middle;
}

label[for=time-factor] {
margin-right: 10px;
}

#time-factor {
width: 150px;
}
</style>
</head>
<body>
<div id="solar-system">
<div id="sun"></div>
<div id="mercury" class="planet"></div>
<div id="venus" class="planet"></div>
<div id="earth" class="planet"></div>
</div>
<label for="time-factor">Time factor:</label>
<input type="range" id="time-factor" min="0.1" max="10" step="0.1" value="1000">
<script>
const timeFactorInput = document.getElementById('time-factor');
const mercury = document.getElementById('mercury');
const venus = document.getElementById('venus');
const earth = document.getElementById('earth');
const inclination = 7;
const perihelion = { mercury: 46, venus: 107, earth: 147 };
const aphelion = { mercury: 69, venus: 109, earth: 152 };
const eccentricity = { mercury: 0.21, venus: 0.01, earth: 0.02 };
const siderealPeriod = { mercury: 88, venus: 224.7, earth: 365.25 };
const orbitalPeriod = { mercury: 87.97, venus: 224.7, earth: 365.25 };
const planetAxisAngle = { mercury: 0.01, venus: 2.64, earth: 23.44 };

let lastTime = null;
let timeElapsed = 0;
let timeFactor = 1;

function updateTimeFactor() {
timeFactor = parseFloat(timeFactorInput.value);
}

timeFactorInput.addEventListener('change', updateTimeFactor);

function animate(now) {
if (!lastTime) {
lastTime = now;
}
const deltaTime = now - lastTime;
lastTime = now;

timeElapsed += deltaTime * timeFactor;
const mercuryAngle = ((timeElapsed / (orbitalPeriod.mercury * 24 * 60 * 60)) * 360) + ((360 / siderealPeriod.mercury) * timeElapsed) - (planetAxisAngle.mercury * inclination);
const venusAngle = ((timeElapsed / (orbitalPeriod.venus * 24 * 60 * 60)) * 360) + ((360 / siderealPeriod.venus) * timeElapsed) - (planetAxisAngle.venus * inclination);
const earthAngle = ((timeElapsed / (orbitalPeriod.earth * 24 * 60 * 60)) * 360) + ((360 / siderealPeriod.earth) * timeElapsed) - (planetAxisAngle.earth * inclination);

const mercuryPerihelion = perihelion.mercury * (1 + eccentricity.mercury);
const mercuryAphelion = perihelion.mercury * (1 - eccentricity.mercury);
const mercuryDistance = ((mercuryPerihelion - mercuryAphelion) / 2) + mercuryAphelion;
mercury.style.transform = 'rotateY(' + mercuryAngle + 'deg) translateX(' + (-mercuryDistance) + 'px) translateY(' + ((-1 * mercuryDistance) / 10) + 'px) translateZ(' + mercuryDistance / 10 + 'px) rotateY(' + (-mercuryAngle) + 'deg)';

const venusPerihelion = perihelion.venus * (1 + eccentricity.venus);
const venusAphelion = perihelion.venus * (1 - eccentricity.venus);
const venusDistance = ((venusPerihelion - venusAphelion) / 2) + venusAphelion;
venus.style.transform = 'rotateY(' + venusAngle + 'deg) translateX(' + (-venusDistance) + 'px) translateY(' + ((-1 * venusDistance) / 10) + 'px) translateZ(' + venusDistance / 10 + 'px) rotateY(' + (-venusAngle) + 'deg)';

const earthPerihelion = perihelion.earth * (1 + eccentricity.earth);
const earthAphelion = perihelion.earth * (1 - eccentricity.earth);
const earthDistance = ((earthPerihelion - earthAphelion) / 2) + earthAphelion;
earth.style.transform = 'rotateY(' + earthAngle + 'deg) translateX(' + (-earthDistance) + 'px) translateY(' + ((-1 * earthDistance) / 10) + 'px) translateZ(' + earthDistance / 10 + 'px) rotateY(' + (-earthAngle) + 'deg)';

requestAnimationFrame(animate);
}

animate(0);
const solarSystem = document.getElementById('solar-system');
let isDragging = false;
let previousMouseX = null;

function onMouseMove(event) {
  if (!isDragging) {
    return;
  }
  const deltaX = event.clientX - previousMouseX;
  previousMouseX = event.clientX;

  solarSystem.style.transform += 'rotateY(' + deltaX + 'deg)';
}

function onMouseUp() {
  isDragging = false;
}

function onMouseDown(event) {
  isDragging = true;
  previousMouseX = event.clientX;
}

solarSystem.addEventListener('mousemove', onMouseMove);
solarSystem.addEventListener('mouseup', onMouseUp);
solarSystem.addEventListener('mousedown', onMouseDown);
</script>
</body>
</html>











































const canvas = document.createElement('canvas');
canvas.width = Math.max(1, window.innerWidth);
canvas.height = Math.max(1, window.innerHeight);
document.body.appendChild(canvas);

const ctx = canvas.getContext('2d');

const sunPos = { x: 1, y: 1, z: 1, size: 20 };
const mercuryPos = { x: 50, y: 0, z: 0, size: 3 };
const venusPos = { x: 70, y: 0, z: -10, size: 4 };
const earthPos = { x: 130, y: 0, z: 0, size: 5 };
let rotation = { x: 0, y: 0, z: 0 };

function drawSolarSystem() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Draw Milky Way background
ctx.globalCompositeOperation = 'lighter';
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'lighter';
for (let i = 0; i < 1000; i++) {
const size = Math.random() * 2;
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, ' + 0.1 + ')';
ctx.fill();
}

// Draw radial grid
drawRadialGrid();

// Draw the Sun
const sunPos2D = projectTo2D(sunPos.x, sunPos.y, sunPos.z);
drawPlanet(sunPos2D.x, sunPos2D.y, sunPos.size, '#ffcc00');

// Draw Mercury
const mercPos2D = projectTo2D(mercuryPos.x - sunPos.x, mercuryPos.y - sunPos.y, mercuryPos.z - sunPos.z);
drawPlanet(mercPos2D.x, mercPos2D.y, mercuryPos.size, '#ff6666');

// Draw Venus
const venusPos2D = projectTo2D(venusPos.x - sunPos.x, venusPos.y - sunPos.y, venusPos.z - sunPos.z);
drawPlanet(venusPos2D.x, venusPos2D.y, venusPos.size, '#ffa500');

// Draw Earth
const earthPos2D = projectTo2D(earthPos.x - sunPos.x, earthPos.y - sunPos.y, earthPos.z - sunPos.z);
drawPlanet(earthPos2D.x, earthPos2D.y, earthPos.size, '#6699ff');

// Update planet positions for the next frame
updatePlanetPositions();

// Update rotation angles based on mouse position
let isDragging = false;
let initialMousePos = { x: 0, y: 0 }; // store initial mouse position when dragging starts
let currentRotation = { x: rotation.x, y: rotation.y }; // initialize current rotation angles to the current rotation
let prevRotation = { x: 0, y: 0 }; // store previous (last) rotation angles

canvas.addEventListener('mousedown', function (event) {
isDragging = true;
initialMousePos.x = event.clientX;
initialMousePos.y = event.clientY;
prevRotation.x = currentRotation.x; // store previous rotation angles
prevRotation.y = currentRotation.y;
});

canvas.addEventListener('mouseup', function (event) {
isDragging = false;
});

canvas.addEventListener('mousemove', function (event) {
if (isDragging) {
// calculate new rotation angles based on difference between current mouse position and initial mouse position
currentRotation.x = prevRotation.x + (event.clientY - initialMousePos.y) / canvas.height * Math.PI;
currentRotation.y = prevRotation.y + (event.clientX - initialMousePos.x) / canvas.width * Math.PI;

// update lastRotation whenever rotation angles are set to new values
if (currentRotation.x !== prevRotation.x || currentRotation.y !== prevRotation.y) {
rotation.x = currentRotation.x;
rotation.y = currentRotation.y;
}
}
});
}

function drawRadialGrid() {
const farthestPlanetRadius = earthPos.x;
const center = { x: canvas.width / 2, y: canvas.height / 2 };

ctx.beginPath();
ctx.arc(center.x, center.y, farthestPlanetRadius, 0, Math.PI * 2);
ctx.closePath();
ctx.setLineDash([5, 5]);
ctx.strokeStyle = 'lightgray';
ctx.stroke();

ctx.setLineDash([]);
for (let radius = 10; radius <= farthestPlanetRadius; radius += 10) {
if (radius <= 0) continue; // skip negative/zero radii
ctx.beginPath();
ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
ctx.closePath();
ctx.strokeStyle = 'lightgray';
ctx.stroke();
}
}
function updatePlanetPositions() {
// Update Mercury's position
mercuryPos.x = 50 * Math.cos(Date.now() / 1000) + sunPos.x;
mercuryPos.z = 50 * Math.sin(Date.now() / 1000) + sunPos.z;

// Update Venus's position
venusPos.x = 70 * Math.cos(Date.now() / 1500) + sunPos.x;
venusPos.z = -10 * Math.sin(Date.now() / 1500) + sunPos.z;

// Update Earth's position
earthPos.y = 100 * Math.cos(Date.now() / 2000) + sunPos.x;
earthPos.z = 100 * Math.sin(Date.now() / 2000) + sunPos.z;
}

function drawPlanet(x, y, size, color) {
size = Math.max(size, 0.1); // size should always be > 0
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}

function projectTo2D(x, y, z) {
const fov = 90; // Field of view angle in degrees
const distance = canvas.width / 2 / Math.tan(fov / 2 * Math.PI / 180);

const cosX = Math.cos(rotation.x);
const sinX = Math.sin(rotation.x);
const cosY = Math.cos(rotation.y);
const sinY = Math.sin(rotation.y);
const cosZ = Math.cos(rotation.z);
const sinZ = Math.sin(rotation.z);

const x1 = x * cosY * cosZ - y * cosY * sinZ + z * sinY;
const y1 = x * (sinX * sinY * cosZ + cosX * sinZ) + y * (sinX * sinY * sinZ - cosX * cosZ) - z * sinX * cosY;
const z1 = x * (cosX * sinY * cosZ - sinX * sinZ) + y * (cosX * sinY * sinZ + sinX * cosZ) + z * cosX * cosY;

const scale = distance / (distance + z1);
const x2d = canvas.width / 2 + x1 * scale;
const y2d = canvas.height / 2 - y1 * scale;

return { x: x2d, y: y2d };
}

function update() {
updatePlanetPositions();
drawSolarSystem();
requestAnimationFrame(update);
}

update();