cosmic-explorer / script.js
zaixx's picture
get real planets position ,time laps s,h,DD,MM,YY
3f7abee verified
// Solar System Simulation
class SolarSystem {
constructor() {
this.canvas = document.getElementById('solarCanvas');
this.ctx = this.canvas.getContext('2d');
this.centerX = 0;
this.centerY = 0;
this.zoom = 1;
this.speed = 1;
this.isPaused = false;
this.time = 0;
this.fps = 60;
this.lastFrameTime = performance.now();
this.startDate = new Date();
this.currentDate = new Date();
this.timeLapseSpeed = 1; // days per frame
this.planets = [
{
name: 'Mercury',
type: 'Terrestrial',
radius: 4,
distance: 60,
orbitalPeriod: 87.97, // days
color: '#9CA3AF',
info: {
diameter: '4,879 km',
moons: 0,
orbitalPeriod: '87.97 days'
},
eccentricity: 0.2056,
inclination: 7.0
},
{
name: 'Venus',
type: 'Terrestrial',
radius: 7,
distance: 85,
orbitalPeriod: 224.70,
color: '#FEF3C7',
info: {
diameter: '12,104 km',
moons: 0,
orbitalPeriod: '224.70 days'
},
eccentricity: 0.0067,
inclination: 3.39
},
{
name: 'Earth',
type: 'Terrestrial',
radius: 8,
distance: 110,
orbitalPeriod: 365.26,
color: '#3B82F6',
info: {
diameter: '12,742 km',
moons: 1,
orbitalPeriod: '365.26 days'
},
moons: [{
radius: 2,
distance: 15,
orbitalPeriod: 27.32, // days
color: '#E5E7EB'
}],
eccentricity: 0.0167,
inclination: 0.0
},
{
name: 'Mars',
type: 'Terrestrial',
radius: 5,
distance: 140,
orbitalPeriod: 686.98,
color: '#EF4444',
info: {
diameter: '6,779 km',
moons: 2,
orbitalPeriod: '686.98 days'
},
moons: [
{
radius: 1,
distance: 10,
orbitalPeriod: 0.32, // days
color: '#F3F4F6'
},
{
radius: 1,
distance: 14,
orbitalPeriod: 1.26, // days
color: '#D1D5DB'
}
],
eccentricity: 0.0935,
inclination: 1.85
},
{
name: 'Jupiter',
type: 'Gas Giant',
radius: 20,
distance: 200,
orbitalPeriod: 4332.59,
color: '#FB923C',
info: {
diameter: '139,820 km',
moons: 79,
orbitalPeriod: '11.86 years'
},
moons: [
{
radius: 2,
distance: 28,
orbitalPeriod: 1.77, // days
color: '#FCD34D'
},
{
radius: 2,
distance: 35,
orbitalPeriod: 3.55, // days
color: '#FDE68A'
}
],
eccentricity: 0.0489,
inclination: 1.31
},
{
name: 'Saturn',
type: 'Gas Giant',
radius: 17,
distance: 260,
orbitalPeriod: 10759.22,
color: '#F59E0B',
hasRings: true,
info: {
diameter: '116,460 km',
moons: 82,
orbitalPeriod: '29.46 years'
},
moons: [
{
radius: 3,
distance: 30,
orbitalPeriod: 2.74, // days
color: '#FBBF24'
}
],
eccentricity: 0.0565,
inclination: 2.49
},
{
name: 'Uranus',
type: 'Ice Giant',
radius: 12,
distance: 320,
orbitalPeriod: 30688.5,
color: '#06B6D4',
info: {
diameter: '50,724 km',
moons: 27,
orbitalPeriod: '84.01 years'
},
eccentricity: 0.0457,
inclination: 0.77
},
{
name: 'Neptune',
type: 'Ice Giant',
radius: 11,
distance: 370,
orbitalPeriod: 60182,
color: '#1E40AF',
info: {
diameter: '49,244 km',
moons: 14,
orbitalPeriod: '164.79 years'
},
eccentricity: 0.0113,
inclination: 1.77
}
];
this.init();
}
init() {
this.resize();
window.addEventListener('resize', () => this.resize());
this.setupEventListeners();
this.createStars();
this.animate();
this.updateDate();
this.updateLocation();
this.updateTimeDisplay();
setInterval(() => this.updateDate(), 1000);
setInterval(() => this.updateLocation(), 30000);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.centerX = this.canvas.width / 2;
this.centerY = this.canvas.height / 2;
}
createStars() {
const starsContainer = document.getElementById('starsContainer');
for (let i = 0; i < 200; i++) {
const star = document.createElement('div');
star.className = 'star';
star.style.width = Math.random() * 3 + 'px';
star.style.height = star.style.width;
star.style.left = Math.random() * 100 + '%';
star.style.top = Math.random() * 100 + '%';
star.style.animationDelay = Math.random() * 3 + 's';
starsContainer.appendChild(star);
}
}
setupEventListeners() {
// Speed control
const speedSlider = document.getElementById('speedSlider');
speedSlider.addEventListener('input', (e) => {
this.speed = parseFloat(e.target.value);
this.timeLapseSpeed = this.speed * 0.1; // Convert to days per frame
document.getElementById('speedValue').textContent = this.speed.toFixed(1) + 'x';
});
// Zoom control
const zoomSlider = document.getElementById('zoomSlider');
zoomSlider.addEventListener('input', (e) => {
this.zoom = parseFloat(e.target.value);
document.getElementById('zoomValue').textContent = this.zoom.toFixed(1) + 'x';
});
// Pause button
const pauseBtn = document.getElementById('pauseBtn');
pauseBtn.addEventListener('click', () => {
this.isPaused = !this.isPaused;
pauseBtn.innerHTML = this.isPaused ?
'<i data-feather="play" class="w-4 h-4"></i><span>Play</span>' :
'<i data-feather="pause" class="w-4 h-4"></i><span>Pause</span>';
feather.replace();
});
// Reset button
document.getElementById('resetBtn').addEventListener('click', () => {
this.time = 0;
this.currentDate = new Date();
this.zoom = 1;
this.speed = 1;
this.timeLapseSpeed = 0.1;
document.getElementById('zoomSlider').value = 1;
document.getElementById('speedSlider').value = 1;
document.getElementById('zoomValue').textContent = '1.0x';
document.getElementById('speedValue').textContent = '1.0x';
this.updateTimeDisplay();
});
// Fullscreen button
document.getElementById('fullscreenBtn').addEventListener('click', () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
}
});
// Info button
document.getElementById('infoBtn').addEventListener('click', () => {
const planetInfo = document.getElementById('planetInfo');
planetInfo.classList.toggle('hidden');
});
// Location refresh on click
document.getElementById('locationDisplay').addEventListener('click', () => {
document.getElementById('locationDisplay').textContent = 'Updating...';
this.updateLocation();
});
// Close info panel
document.getElementById('closeInfo').addEventListener('click', () => {
document.getElementById('planetInfo').classList.add('hidden');
});
// Time jump controls
document.querySelectorAll('.time-unit').forEach(unit => {
unit.addEventListener('click', (e) => {
const jumpDays = parseInt(e.target.dataset.time);
this.time += jumpDays / this.timeLapseSpeed;
this.updateTimeDisplay();
this.updateDate();
});
});
// Canvas click for planet info
this.canvas.addEventListener('click', (e) => {
const rect = this.canvas.getBoundingClientRect();
const x = e.clientX - rect.left - this.centerX;
const y = e.clientY - rect.top - this.centerY;
for (const planet of this.planets) {
const angle = this.time * planet.speed * this.speed * 0.01;
const px = Math.cos(angle) * planet.distance * this.zoom;
const py = Math.sin(angle) * planet.distance * this.zoom;
const distance = Math.sqrt((x - px) ** 2 + (y - py) ** 2);
if (distance < planet.radius * this.zoom + 5) {
this.showPlanetInfo(planet);
break;
}
}
});
}
showPlanetInfo(planet) {
const info = document.getElementById('planetInfo');
info.classList.remove('hidden');
document.getElementById('planetName').textContent = planet.name;
document.getElementById('planetType').textContent = planet.type;
document.getElementById('planetDistance').textContent = planet.distance + ' AU';
document.getElementById('planetPeriod').textContent = planet.info.orbitalPeriod;
document.getElementById('planetDiameter').textContent = planet.info.diameter;
document.getElementById('planetMoons').textContent = planet.info.moons || 'None';
}
updateTimeDisplay() {
const timeDisplay = document.getElementById('timeDisplay');
if (timeDisplay) {
const days = Math.floor(this.timeLapseSpeed * this.time);
const years = Math.floor(days / 365.26);
const remainingDays = days % 365.26;
const months = Math.floor(remainingDays / 30.44);
const remainingDays2 = Math.floor(remainingDays % 30.44);
let timeString = '';
if (years > 0) timeString += `${years}Y `;
if (months > 0) timeString += `${months}M `;
if (remainingDays2 > 0 || timeString === '') timeString += `${remainingDays2}D`;
timeDisplay.textContent = `Time Lapse: ${timeString}`;
}
}
calculatePlanetPosition(planet, elapsedTime) {
const meanAnomaly = (2 * Math.PI * elapsedTime) / planet.orbitalPeriod;
const eccentricity = planet.eccentricity || 0;
// Solve Kepler's equation (simplified)
let E = meanAnomaly;
for (let i = 0; i < 5; i++) {
E = meanAnomaly + eccentricity * Math.sin(E);
}
// True anomaly
const trueAnomaly = 2 * Math.atan2(
Math.sqrt(1 + eccentricity) * Math.sin(E / 2),
Math.sqrt(1 - eccentricity) * Math.cos(E / 2)
);
// Distance from sun
const r = planet.distance * (1 - eccentricity * Math.cos(E));
// Position
const x = r * Math.cos(trueAnomaly);
const y = r * Math.sin(trueAnomaly);
// Apply inclination
const inclination = (planet.inclination || 0) * Math.PI / 180;
const yInclined = y * Math.cos(inclination);
return { x, y: yInclined, r };
}
updateDate() {
const now = new Date();
document.getElementById('dateDisplay').textContent = now.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
// Update current date display
const currentDateDisplay = document.getElementById('currentDateDisplay');
if (currentDateDisplay) {
currentDateDisplay.textContent = this.currentDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}
}
async updateLocation() {
const locationDisplay = document.getElementById('locationDisplay');
if (!navigator.geolocation) {
locationDisplay.textContent = 'Location not supported';
return;
}
navigator.geolocation.getCurrentPosition(
async (position) => {
const { latitude, longitude } = position.coords;
try {
// Using Nominatim reverse geocoding API
const response = await fetch(
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=10`,
{
headers: {
'User-Agent': 'CosmicExplorer/1.0'
}
}
);
if (!response.ok) throw new Error('Location fetch failed');
const data = await response.json();
const city = data.address?.city || data.address?.town || data.address?.village || 'Unknown';
const country = data.address?.country || '';
locationDisplay.textContent = country ? `${city}, ${country}` : city;
} catch (error) {
// Fallback to coordinates
locationDisplay.textContent = `${latitude.toFixed(2)}°, ${longitude.toFixed(2)}°`;
}
},
(error) => {
locationDisplay.textContent = 'Location denied';
}
);
}
drawSun() {
// Simplified sun for performance
this.ctx.fillStyle = '#FBBF24';
this.ctx.beginPath();
this.ctx.arc(this.centerX, this.centerY, 25 * this.zoom, 0, Math.PI * 2);
this.ctx.fill();
// Simple glow effect
this.ctx.fillStyle = 'rgba(251, 191, 36, 0.3)';
this.ctx.beginPath();
this.ctx.arc(this.centerX, this.centerY, 35 * this.zoom, 0, Math.PI * 2);
this.ctx.fill();
}
drawPlanet(planet) {
const elapsedTime = this.timeLapseSpeed * this.time;
const position = this.calculatePlanetPosition(planet, elapsedTime);
const x = this.centerX + position.x * this.zoom;
const y = this.centerY + position.y * this.zoom;
// Draw orbit
this.ctx.strokeStyle = 'rgba(147, 51, 234, 0.2)';
this.ctx.lineWidth = 1;
this.ctx.beginPath();
this.ctx.ellipse(this.centerX, this.centerY, planet.distance * this.zoom, planet.distance * this.zoom, 0, 0, Math.PI * 2);
this.ctx.stroke();
// Draw rings for Saturn
if (planet.hasRings) {
this.ctx.strokeStyle = 'rgba(245, 158, 11, 0.5)';
this.ctx.lineWidth = 3 * this.zoom;
this.ctx.beginPath();
this.ctx.ellipse(x, y, planet.radius * this.zoom * 2, planet.radius * this.zoom * 0.7, 0, 0, Math.PI * 2);
this.ctx.stroke();
}
// Draw planet
this.ctx.fillStyle = planet.color;
this.ctx.beginPath();
this.ctx.arc(x, y, planet.radius * this.zoom, 0, Math.PI * 2);
this.ctx.fill();
// Draw moons
if (planet.moons) {
planet.moons.forEach(moon => {
const moonElapsedTime = this.timeLapseSpeed * this.time;
const moonAngle = (2 * Math.PI * moonElapsedTime) / moon.orbitalPeriod;
const moonX = x + Math.cos(moonAngle) * moon.distance * this.zoom;
const moonY = y + Math.sin(moonAngle) * moon.distance * this.zoom;
this.ctx.fillStyle = moon.color;
this.ctx.beginPath();
this.ctx.arc(moonX, moonY, moon.radius * this.zoom, 0, Math.PI * 2);
this.ctx.fill();
});
}
// Draw planet name
if (this.zoom > 0.8) {
this.ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
this.ctx.font = `${Math.max(10, 10 * this.zoom)}px Arial`;
this.ctx.textAlign = 'center';
this.ctx.fillText(planet.name, x, y - planet.radius * this.zoom - 5);
}
return { x, y, position };
}
adjustBrightness(color, amount) {
const num = parseInt(color.replace('#', ''), 16);
const r = Math.max(0, Math.min(255, (num >> 16) + amount));
const g = Math.max(0, Math.min(255, ((num >> 8) & 0x00FF) + amount));
const b = Math.max(0, Math.min(255, (num & 0x0000FF) + amount));
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
}
animate() {
// Clear canvas completely for better performance
this.ctx.fillStyle = '#000';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// Draw sun
this.drawSun();
// Draw planets
this.planets.forEach(planet => this.drawPlanet(planet));
// Update time
if (!this.isPaused) {
this.time++;
this.currentDate = new Date(this.startDate.getTime() + this.timeLapseSpeed * this.time * 24 * 60 * 60 * 1000);
this.updateTimeDisplay();
}
// Update stats less frequently
if (this.time % 10 === 0) {
this.updateStats();
}
// Calculate FPS
const now = performance.now();
const delta = now - this.lastFrameTime;
this.fps = Math.round(1000 / delta);
this.lastFrameTime = now;
requestAnimationFrame(() => this.animate());
}
updateStats() {
document.getElementById('fpsDisplay').textContent = this.fps;
const totalDays = Math.floor(this.timeLapseSpeed * this.time);
document.getElementById('daysDisplay').textContent = totalDays;
document.getElementById('yearsDisplay').textContent = (totalDays / 365.26).toFixed(2);
}
}
// Initialize the solar system
document.addEventListener('DOMContentLoaded', () => {
new SolarSystem();
});