From 5f47ec16592c76c79eace08111ecef0c55e1a4ad Mon Sep 17 00:00:00 2001 From: rayd1o Date: Sun, 26 Apr 2026 01:41:29 +0800 Subject: [PATCH] release: bump version to 0.40.4 --- VERSION | 2 +- docs/CHANGELOG.md | 12 +++++ docs/version-history.md | 3 +- frontend/package.json | 2 +- frontend/public/earth/js/main.js | 17 +++++++ frontend/public/earth/js/satellites.js | 69 ++++++++++++++++++-------- pyproject.toml | 2 +- uv.lock | 2 +- 8 files changed, 83 insertions(+), 26 deletions(-) diff --git a/VERSION b/VERSION index 909f3ee5..f57373a0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.40.3 \ No newline at end of file +0.40.4 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9a9eaa8b..363a05a9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,18 @@ This project follows the repository versioning rule: ## [0.39.0] — 2026-04-24 +## [0.40.4] — 2026-04-26 + +### 🔧 Improvements +- 新增页面可见性恢复处理,页面从后台切回前台时主动刷新卫星位置,避免累积后台时间在下一帧一次性回放 +- 抽出卫星轨迹状态与轨迹几何清理 helper,统一后台恢复与清空数据时的轨迹重置路径 + +### 🐛 Fixes +- 修复页面在后台停留较久后恢复前台时,卫星轨迹因超大 `deltaTime` 突然跳变、拖尾异常拉长的问题 +- 修复后台恢复后首帧仍沿用旧轨迹缓存,导致轨迹与当前卫星位置短时错位的问题 + +--- + ## [0.40.3] — 2026-04-25 ### 🔧 Improvements diff --git a/docs/version-history.md b/docs/version-history.md index 18d0b979..3f0f3149 100644 --- a/docs/version-history.md +++ b/docs/version-history.md @@ -16,12 +16,13 @@ ## Current Version - `main` 当前主线历史推导到:`0.16.5` -- `dev` 当前开发分支历史推导到:`0.40.3` +- `dev` 当前开发分支历史推导到:`0.40.4` ## Timeline | Version | Type | Branch | Commit | Summary | | --- | --- | --- | --- | --- | +| `0.40.4` | bugfix | `dev` | `pending` | 修复页面后台恢复后卫星轨迹跳变与位置错位,统一轨迹重置路径 | | `0.40.3` | improvement | `dev` | `pending` | 卫星点云升级 ShaderMaterial,修复锁定环 depthTest 与位置漂移,新增悬停态缩放 | | `0.40.2` | improvement | `dev` | `pending` | 卫星点大小随镜头缩放动态调整,调小默认基础尺寸 | | `0.40.1` | improvement | `dev` | `pending` | 卫星选中标记配色跟随图例,修复 footprint 遮蔽卫星渲染问题,修复选中海缆误触发卫星高亮 | diff --git a/frontend/package.json b/frontend/package.json index 24682574..ee6427a2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "planet-frontend", - "version": "0.40.3", + "version": "0.40.4", "private": true, "packageManager": "bun@1", "dependencies": { diff --git a/frontend/public/earth/js/main.js b/frontend/public/earth/js/main.js index 8741740d..2ddcf9de 100644 --- a/frontend/public/earth/js/main.js +++ b/frontend/public/earth/js/main.js @@ -242,6 +242,7 @@ let activeTouchPoints = new Map(); let pinchGesture = null; let pointerDragDistance = 0; let suppressNextClick = false; +let shouldRefreshSatellitesAfterVisibilityResume = false; const clock = new THREE.Clock(); const interactionRaycaster = new THREE.Raycaster(); @@ -2392,6 +2393,7 @@ export async function setSatellitesEnabled( function setupEventListeners() { const handleResize = () => onWindowResize(); + const handleVisibilityChange = () => onVisibilityChange(); const handlePointerMove = (event) => onPointerMove(event); const handlePointerDown = (event) => onPointerDown(event); const handlePointerUp = (event) => onPointerUp(event); @@ -2403,6 +2405,7 @@ function setupEventListeners() { const handleInfoCardDrag = () => repositionCruiseConnector(); bindListener(window, "resize", handleResize); + bindListener(document, "visibilitychange", handleVisibilityChange); bindListener(window, "pagehide", handlePageHide); bindListener(window, "beforeunload", handlePageHide); bindListener(window, "earth:rotation-mode-change", handleRotationMode); @@ -2425,6 +2428,20 @@ function setupEventListeners() { } } +function onVisibilityChange() { + if (document.hidden) { + shouldRefreshSatellitesAfterVisibilityResume = true; + return; + } + + if (!shouldRefreshSatellitesAfterVisibilityResume) return; + shouldRefreshSatellitesAfterVisibilityResume = false; + + // Drop the elapsed background time so the next RAF does not replay it. + clock.getDelta(); + updateSatellitePositions(0, true, { resetTrails: true }); +} + function updateHudScale() { const widthScale = window.innerWidth / HUD_CONFIG.scaleReferenceWidth; const heightScale = window.innerHeight / HUD_CONFIG.scaleReferenceHeight; diff --git a/frontend/public/earth/js/satellites.js b/frontend/public/earth/js/satellites.js index e93707e4..45be0577 100644 --- a/frontend/public/earth/js/satellites.js +++ b/frontend/public/earth/js/satellites.js @@ -68,6 +68,7 @@ const SATELLITE_CONSTELLATION_LABELS = Object.freeze({ const TRAIL_LENGTH = SATELLITE_CONFIG.trailLength; const DOT_TEXTURE_SIZE = 32; const POSITION_UPDATE_INTERVAL_MS = 250; +const BACKGROUND_TRAIL_RESET_DELTA_MS = 2000; const DIMMED_SATELLITE_BRIGHTNESS = 0.42; const DIMMED_SATELLITE_TRAIL_BRIGHTNESS = 0.24; const DIMMED_SATELLITE_POINT_OPACITY = 0.62; @@ -556,6 +557,34 @@ function createSatellitePositionState() { }; } +function resetSatelliteTrailState() { + satellitePositions.forEach((position) => { + position.trail = []; + position.trailIndex = 0; + position.trailCount = 0; + }); +} + +function clearSatelliteTrailGeometry() { + if (!satelliteTrails) return; + + const trailPositionAttr = satelliteTrails.geometry.attributes.position; + const trailColorAttr = satelliteTrails.geometry.attributes.color; + if (trailPositionAttr?.array) { + trailPositionAttr.array.fill(0); + trailPositionAttr.needsUpdate = true; + } + if (trailColorAttr?.array) { + trailColorAttr.array.fill(0); + trailColorAttr.needsUpdate = true; + } +} + +function clearSatelliteTrails() { + resetSatelliteTrailState(); + clearSatelliteTrailGeometry(); +} + function ensureSatelliteCapacity(count) { if (!satellitePoints || !satelliteBackdropPoints || !satelliteTrails) return; @@ -925,21 +954,32 @@ export async function loadSatellites(options = {}) { }; } -export function updateSatellitePositions(deltaTime = 0, force = false) { +export function updateSatellitePositions(deltaTime = 0, force = false, options = {}) { if (!satellitePoints || !satelliteBackdropPoints || satelliteData.length === 0) return; const shouldUpdateTrails = showSatellites || showTrails || lockedSatelliteIndex !== null; - positionUpdateAccumulator += deltaTime; + const shouldResetTrails = + options.resetTrails || + (!force && deltaTime >= BACKGROUND_TRAIL_RESET_DELTA_MS); + + if (shouldResetTrails) { + clearSatelliteTrails(); + positionUpdateAccumulator = POSITION_UPDATE_INTERVAL_MS; + } else { + positionUpdateAccumulator += deltaTime; + } if (!force && positionUpdateAccumulator < POSITION_UPDATE_INTERVAL_MS) { return; } - const elapsedMs = Math.max( - positionUpdateAccumulator, - POSITION_UPDATE_INTERVAL_MS, - ); + const elapsedMs = shouldResetTrails + ? 0 + : Math.max( + positionUpdateAccumulator, + POSITION_UPDATE_INTERVAL_MS, + ); positionUpdateAccumulator = 0; const positions = satellitePoints.geometry.attributes.position.array; @@ -2384,10 +2424,8 @@ export function clearSatelliteData() { satellitePositions.forEach((position) => { position.current.set(0, 0, 0); - position.trail = []; - position.trailIndex = 0; - position.trailCount = 0; }); + resetSatelliteTrailState(); if (satellitePoints) { const positionAttr = satellitePoints.geometry.attributes.position; @@ -2424,18 +2462,7 @@ export function clearSatelliteData() { satelliteBackdropPoints.geometry.setDrawRange(0, 0); } - if (satelliteTrails) { - const trailPositionAttr = satelliteTrails.geometry.attributes.position; - const trailColorAttr = satelliteTrails.geometry.attributes.color; - if (trailPositionAttr?.array) { - trailPositionAttr.array.fill(0); - trailPositionAttr.needsUpdate = true; - } - if (trailColorAttr?.array) { - trailColorAttr.array.fill(0); - trailColorAttr.needsUpdate = true; - } - } + clearSatelliteTrailGeometry(); hideHoverRings(); hideLockedRing(); diff --git a/pyproject.toml b/pyproject.toml index 3ca375e4..b791d0c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "planet" -version = "0.40.3" +version = "0.40.4" description = "智能星球计划 - 态势感知系统" requires-python = ">=3.14" dependencies = [ diff --git a/uv.lock b/uv.lock index 04025565..4ab1ce6f 100644 --- a/uv.lock +++ b/uv.lock @@ -475,7 +475,7 @@ wheels = [ [[package]] name = "planet" -version = "0.40.3" +version = "0.40.4" source = { virtual = "." } dependencies = [ { name = "aiofiles" },