fix: Globe now rotates to always show ISS position

- Globe view centers on ISS longitude so it's always visible
- Added console logging for debugging position updates
- Increased ISS marker size and glow for better visibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-29 16:35:30 +00:00
parent 0aaa18ae33
commit 407f2a9e6d
+49 -50
View File
@@ -176,17 +176,21 @@ const SSTV = (function() {
* Fetch current ISS position * Fetch current ISS position
*/ */
async function updateIssPosition() { async function updateIssPosition() {
const storedLat = localStorage.getItem('observerLat') || 51.5074; const storedLat = localStorage.getItem('observerLat') || '51.5074';
const storedLon = localStorage.getItem('observerLon') || -0.1278; const storedLon = localStorage.getItem('observerLon') || '-0.1278';
try { try {
const response = await fetch(`/sstv/iss-position?latitude=${storedLat}&longitude=${storedLon}`); const url = `/sstv/iss-position?latitude=${storedLat}&longitude=${storedLon}`;
const response = await fetch(url);
const data = await response.json(); const data = await response.json();
if (data.status === 'ok') { if (data.status === 'ok') {
issPosition = data; issPosition = data;
updateIssDisplay(); updateIssDisplay();
renderGlobe(); renderGlobe();
console.log('ISS position updated:', data.lat.toFixed(1), data.lon.toFixed(1));
} else {
console.warn('ISS position error:', data.message);
} }
} catch (err) { } catch (err) {
console.error('Failed to get ISS position:', err); console.error('Failed to get ISS position:', err);
@@ -209,7 +213,7 @@ const SSTV = (function() {
} }
/** /**
* Render 3D globe with ISS position * Render 3D globe with ISS position - globe rotates to center on ISS
*/ */
function renderGlobe() { function renderGlobe() {
const canvas = document.getElementById('sstvGlobe'); const canvas = document.getElementById('sstvGlobe');
@@ -220,6 +224,9 @@ const SSTV = (function() {
const cy = canvas.height / 2; const cy = canvas.height / 2;
const radius = Math.min(cx, cy) - 10; const radius = Math.min(cx, cy) - 10;
// Globe rotation - center on ISS longitude if available
const globeRotation = issPosition ? -issPosition.lon : 0;
// Clear canvas // Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -247,75 +254,67 @@ const SSTV = (function() {
ctx.stroke(); ctx.stroke();
} }
// Longitude lines // Longitude lines (rotated with globe)
for (let lon = 0; lon < 180; lon += 30) { for (let lon = 0; lon < 180; lon += 30) {
ctx.beginPath(); const rotatedLon = lon + globeRotation;
ctx.ellipse(cx, cy, radius * Math.cos(lon * Math.PI / 180), radius, 0, 0, Math.PI * 2); const xScale = Math.cos(rotatedLon * Math.PI / 180);
ctx.stroke(); if (Math.abs(xScale) > 0.1) {
ctx.beginPath();
ctx.ellipse(cx, cy, Math.abs(xScale) * radius, radius, 0, 0, Math.PI * 2);
ctx.stroke();
}
} }
// Draw simple landmasses (simplified continents) // Draw ISS position - always visible since globe is centered on it
ctx.fillStyle = 'rgba(0, 180, 100, 0.3)';
ctx.strokeStyle = 'rgba(0, 200, 120, 0.4)';
ctx.lineWidth = 1;
// Draw ISS position
if (issPosition) { if (issPosition) {
const issLat = issPosition.lat; const issLat = issPosition.lat;
const issLon = issPosition.lon;
// Convert lat/lon to x/y on globe (simple projection) // ISS is always at center horizontally (globe rotated to it)
// Only show if on visible hemisphere (simplified: lon between -90 and 90) const x = cx;
const normalizedLon = ((issLon + 180) % 360) - 180; const y = cy - (issLat / 90) * radius;
const visibleRange = 90;
if (Math.abs(normalizedLon) <= visibleRange) { // ISS glow
const x = cx + (normalizedLon / 90) * radius * Math.cos(issLat * Math.PI / 180); const issGradient = ctx.createRadialGradient(x, y, 0, x, y, 20);
const y = cy - (issLat / 90) * radius; issGradient.addColorStop(0, 'rgba(0, 212, 255, 0.9)');
issGradient.addColorStop(0.4, 'rgba(0, 212, 255, 0.4)');
issGradient.addColorStop(1, 'rgba(0, 212, 255, 0)');
// ISS glow ctx.beginPath();
const issGradient = ctx.createRadialGradient(x, y, 0, x, y, 15); ctx.arc(x, y, 20, 0, Math.PI * 2);
issGradient.addColorStop(0, 'rgba(0, 212, 255, 0.8)'); ctx.fillStyle = issGradient;
issGradient.addColorStop(0.5, 'rgba(0, 212, 255, 0.3)'); ctx.fill();
issGradient.addColorStop(1, 'rgba(0, 212, 255, 0)');
ctx.beginPath(); // ISS dot
ctx.arc(x, y, 15, 0, Math.PI * 2); ctx.beginPath();
ctx.fillStyle = issGradient; ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fill(); ctx.fillStyle = '#00d4ff';
ctx.fill();
ctx.strokeStyle = '#fff';
ctx.lineWidth = 2;
ctx.stroke();
// ISS dot // ISS label
ctx.beginPath(); ctx.fillStyle = '#00d4ff';
ctx.arc(x, y, 4, 0, Math.PI * 2); ctx.font = 'bold 10px JetBrains Mono, monospace';
ctx.fillStyle = '#00d4ff'; ctx.textAlign = 'center';
ctx.fill(); ctx.fillText('ISS', x, y - 15);
ctx.strokeStyle = '#fff';
ctx.lineWidth = 1.5;
ctx.stroke();
// ISS label
ctx.fillStyle = '#00d4ff';
ctx.font = 'bold 9px JetBrains Mono, monospace';
ctx.textAlign = 'center';
ctx.fillText('ISS', x, y - 12);
}
} }
// Draw globe edge highlight // Draw globe edge highlight
ctx.beginPath(); ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2); ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(0, 212, 255, 0.3)'; ctx.strokeStyle = 'rgba(0, 212, 255, 0.4)';
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.stroke(); ctx.stroke();
// Atmospheric glow // Atmospheric glow
const atmoGradient = ctx.createRadialGradient(cx, cy, radius - 5, cx, cy, radius + 8); const atmoGradient = ctx.createRadialGradient(cx, cy, radius - 5, cx, cy, radius + 10);
atmoGradient.addColorStop(0, 'rgba(0, 212, 255, 0)'); atmoGradient.addColorStop(0, 'rgba(0, 212, 255, 0)');
atmoGradient.addColorStop(0.5, 'rgba(0, 212, 255, 0.1)'); atmoGradient.addColorStop(0.6, 'rgba(0, 212, 255, 0.15)');
atmoGradient.addColorStop(1, 'rgba(0, 212, 255, 0)'); atmoGradient.addColorStop(1, 'rgba(0, 212, 255, 0)');
ctx.beginPath(); ctx.beginPath();
ctx.arc(cx, cy, radius + 8, 0, Math.PI * 2); ctx.arc(cx, cy, radius + 10, 0, Math.PI * 2);
ctx.fillStyle = atmoGradient; ctx.fillStyle = atmoGradient;
ctx.fill(); ctx.fill();
} }