From 465129eec7e8d5edb4223a5f813f662baa5e8f8f Mon Sep 17 00:00:00 2001 From: rayd1o Date: Mon, 23 Mar 2026 03:56:45 +0800 Subject: [PATCH] fix(satellites): use timestamp-based trail filtering to prevent flash - Changed trail data structure to {pos, time} with Date.now() timestamp - Replaced length-based filtering with time-based filtering (5 second window) - Trail now naturally clears when page returns to foreground - No more ugly frame-skipping or visibilitychange workarounds Build: passes --- frontend/public/earth/js/satellites.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/public/earth/js/satellites.js b/frontend/public/earth/js/satellites.js index 06a513dd..3420b478 100644 --- a/frontend/public/earth/js/satellites.js +++ b/frontend/public/earth/js/satellites.js @@ -18,6 +18,7 @@ let lockedRingSprite = null; const SATELLITE_API = SATELLITE_CONFIG.apiPath + '?limit=' + SATELLITE_CONFIG.maxCount; const MAX_SATELLITES = SATELLITE_CONFIG.maxCount; const TRAIL_LENGTH = SATELLITE_CONFIG.trailLength; +const TRAIL_MAX_AGE_MS = 5000; // 5 seconds const DOT_TEXTURE_SIZE = 32; function createCircularDotTexture() { @@ -244,10 +245,10 @@ export function updateSatellitePositions(deltaTime = 0) { satellitePositions[i].current.copy(pos); - satellitePositions[i].trail.push(pos.clone()); - if (satellitePositions[i].trail.length > TRAIL_LENGTH) { - satellitePositions[i].trail.shift(); - } + satellitePositions[i].trail.push({ pos: pos.clone(), time: Date.now() }); + satellitePositions[i].trail = satellitePositions[i].trail.filter( + p => Date.now() - p.time < TRAIL_MAX_AGE_MS + ); positions[i * 3] = pos.x; positions[i * 3 + 1] = pos.y; @@ -281,7 +282,7 @@ export function updateSatellitePositions(deltaTime = 0) { const trailIdx = (i * TRAIL_LENGTH + j) * 3; if (j < trail.length) { - const t = trail[j]; + const t = trail[j].pos; trailPositions[trailIdx] = t.x; trailPositions[trailIdx + 1] = t.y; trailPositions[trailIdx + 2] = t.z;