mirror of
https://github.com/smittix/intercept.git
synced 2026-07-31 11:53:05 -07:00
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:
+49
-50
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user