release: bump version to 0.55.0
This commit is contained in:
@@ -1390,12 +1390,13 @@
|
||||
.earth-mobile-settings-switch-track::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
top: 50%;
|
||||
left: 4px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transform: translateY(-50%);
|
||||
transition: transform 0.18s ease;
|
||||
}
|
||||
|
||||
@@ -1404,7 +1405,7 @@
|
||||
}
|
||||
|
||||
.earth-mobile-settings-switch input:checked + .earth-mobile-settings-switch-track::after {
|
||||
transform: translateX(16px);
|
||||
transform: translate(16px, -50%);
|
||||
}
|
||||
|
||||
label.is-disabled.earth-mobile-settings-card {
|
||||
@@ -2477,13 +2478,14 @@ label.is-disabled.earth-mobile-settings-card {
|
||||
.earth-settings-switch-track::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(3px * var(--hud-scale));
|
||||
top: 50%;
|
||||
left: calc(3px * var(--hud-scale));
|
||||
width: calc(16px * var(--hud-scale));
|
||||
height: calc(16px * var(--hud-scale));
|
||||
border-radius: 50%;
|
||||
background: #edf4fc;
|
||||
box-shadow: 0 6px 14px rgba(1, 8, 18, 0.26);
|
||||
transform: translateY(-50%);
|
||||
transition: transform 0.18s ease;
|
||||
}
|
||||
|
||||
@@ -2493,7 +2495,7 @@ label.is-disabled.earth-mobile-settings-card {
|
||||
}
|
||||
|
||||
.earth-settings-switch input:checked + .earth-settings-switch-track::after {
|
||||
transform: translateX(calc(16px * var(--hud-scale)));
|
||||
transform: translate(calc(16px * var(--hud-scale)), -50%);
|
||||
}
|
||||
|
||||
.earth-settings-item.is-disabled {
|
||||
|
||||
@@ -879,6 +879,16 @@
|
||||
<span class="earth-mobile-settings-switch-track"></span>
|
||||
</span>
|
||||
</label>
|
||||
<label class="earth-mobile-settings-card">
|
||||
<div class="earth-mobile-settings-copy">
|
||||
<span class="earth-mobile-settings-label">真实卫星高度</span>
|
||||
<span class="earth-mobile-settings-subtitle">按真实轨道高度压缩分层显示</span>
|
||||
</div>
|
||||
<span class="earth-mobile-settings-switch">
|
||||
<input type="checkbox" data-satellite-real-altitude-toggle checked>
|
||||
<span class="earth-mobile-settings-switch-track"></span>
|
||||
</span>
|
||||
</label>
|
||||
<label class="earth-mobile-settings-card">
|
||||
<div class="earth-mobile-settings-copy">
|
||||
<span class="earth-mobile-settings-label">轨迹显示</span>
|
||||
@@ -1190,6 +1200,16 @@
|
||||
<span class="earth-settings-switch-track"></span>
|
||||
</span>
|
||||
</label>
|
||||
<label class="earth-settings-item" for="toggle-satellite-real-altitude">
|
||||
<div class="earth-settings-copy">
|
||||
<span class="earth-settings-item-title">真实卫星高度</span>
|
||||
<span class="earth-settings-item-subtitle">按真实轨道高度压缩分层显示,关闭后使用旧版同层球面</span>
|
||||
</div>
|
||||
<span class="earth-settings-switch">
|
||||
<input id="toggle-satellite-real-altitude" type="checkbox" data-satellite-real-altitude-toggle checked>
|
||||
<span class="earth-settings-switch-track"></span>
|
||||
</span>
|
||||
</label>
|
||||
<label class="earth-settings-item" for="toggle-trails-display">
|
||||
<div class="earth-settings-copy">
|
||||
<span class="earth-settings-item-title">轨迹显示</span>
|
||||
|
||||
@@ -39,6 +39,15 @@ export const SATELLITE_DISPLAY_STYLES = {
|
||||
export const DEFAULT_SATELLITE_DISPLAY_STYLE =
|
||||
SATELLITE_DISPLAY_STYLES.GROUND_FOOTPRINT;
|
||||
|
||||
export const SURFACE_HOVER_INFO_MODES = {
|
||||
COUNTRY: "country",
|
||||
POSITION: "position",
|
||||
FULL: "full",
|
||||
};
|
||||
|
||||
export const DEFAULT_SURFACE_HOVER_INFO_MODE =
|
||||
SURFACE_HOVER_INFO_MODES.FULL;
|
||||
|
||||
export const CRUISE_CONFIG = {
|
||||
dwellMs: 7_000,
|
||||
focusDurationMs: 1_400,
|
||||
@@ -331,7 +340,11 @@ export const SATELLITE_CONFIG = {
|
||||
hydrateFullAfterInitialLoad: false,
|
||||
trailLength: 10,
|
||||
trailLineWidth: 3,
|
||||
displayAltitudeOffset: 8,
|
||||
fallbackAltitudeOffset: 8,
|
||||
altitudeCompressionKm: 1200,
|
||||
maxDisplayAltitudeKm: 40000,
|
||||
minRealAltitudeOffset: 4,
|
||||
maxRealAltitudeOffset: 55,
|
||||
frontFacingDotThreshold: 0.015,
|
||||
overlayRenderOrder: 12,
|
||||
dotBaseSize: 2.8,
|
||||
|
||||
77
frontend/public/earth/js/controls.js
vendored
77
frontend/public/earth/js/controls.js
vendored
@@ -4,11 +4,13 @@ import * as THREE from "three";
|
||||
import {
|
||||
CONFIG,
|
||||
CRUISE_MODULES,
|
||||
DEFAULT_SURFACE_HOVER_INFO_MODE,
|
||||
DEFAULT_SATELLITE_DISPLAY_STYLE,
|
||||
DEFAULT_CRUISE_MODULES,
|
||||
EARTH_CONFIG,
|
||||
ROTATION_MODE,
|
||||
SATELLITE_DISPLAY_STYLES,
|
||||
SURFACE_HOVER_INFO_MODES,
|
||||
} from "./constants.js";
|
||||
import {
|
||||
setEarthStatValue,
|
||||
@@ -51,7 +53,9 @@ import {
|
||||
getSatelliteCount,
|
||||
getSatelliteDisplayStyle,
|
||||
getSatelliteIdleBreathingEnabled,
|
||||
getSatelliteRealAltitudeEnabled,
|
||||
setSatelliteIdleBreathingEnabled as applySatelliteIdleBreathingEnabled,
|
||||
setSatelliteRealAltitudeEnabled as applySatelliteRealAltitudeEnabled,
|
||||
setSatelliteDisplayStyle as applySatelliteDisplayStyle,
|
||||
} from "./satellites.js";
|
||||
import {
|
||||
@@ -141,7 +145,7 @@ const SETTINGS_SHEET_MAX_SCALE_X = 0.22;
|
||||
const SETTINGS_SHEET_MAX_SCALE_Y = 0.18;
|
||||
const EARTH_SETTINGS_STORAGE_KEY = "planet.earth.settings.v2";
|
||||
const LEGACY_EARTH_SETTINGS_STORAGE_KEY = "planet.earth.settings.v1";
|
||||
const EARTH_SETTINGS_VERSION = 10;
|
||||
const EARTH_SETTINGS_VERSION = 11;
|
||||
const GRID_LINES_DEFAULT_VERSION = 3;
|
||||
const SATELLITE_DISPLAY_DEFAULT_VERSION = 4;
|
||||
const MEDIA_PANEL_DEFAULT_VERSION = 5;
|
||||
@@ -150,6 +154,7 @@ const MOTION_PROVIDER_DEFAULT_VERSION = 7;
|
||||
const MOTION_DEBUG_SKELETON_ONLY_DEFAULT_VERSION = 8;
|
||||
const MEDIA_PANEL_ACTIVE_TAB_DEFAULT_VERSION = 9;
|
||||
const VISUAL_PREFERENCES_DEFAULT_VERSION = 10;
|
||||
const SURFACE_HOVER_INFO_DEFAULT_VERSION = 11;
|
||||
const DEFAULT_EARTH_ZOOM_STEP = 0.01;
|
||||
const ZOOM_STATUS_UPDATE_INTERVAL_MS = 90;
|
||||
const TARGET_SWITCH_ZOOM_IN_PHASE = 0.28;
|
||||
@@ -177,6 +182,9 @@ const ALLOWED_CRUISE_MODULES = new Set(Object.values(CRUISE_MODULES));
|
||||
const ALLOWED_SATELLITE_DISPLAY_STYLES = new Set(
|
||||
Object.values(SATELLITE_DISPLAY_STYLES),
|
||||
);
|
||||
const ALLOWED_SURFACE_HOVER_INFO_MODES = new Set(
|
||||
Object.values(SURFACE_HOVER_INFO_MODES),
|
||||
);
|
||||
const CRUISE_MODULE_LABELS = {
|
||||
[CRUISE_MODULES.BGP]: "BGP",
|
||||
[CRUISE_MODULES.NEWS]: "新闻",
|
||||
@@ -190,6 +198,12 @@ function normalizeMediaPanelActiveTab(tab) {
|
||||
return tab === "news" ? "news" : "live";
|
||||
}
|
||||
|
||||
function normalizeSurfaceHoverInfoMode(mode) {
|
||||
return ALLOWED_SURFACE_HOVER_INFO_MODES.has(mode)
|
||||
? mode
|
||||
: DEFAULT_SURFACE_HOVER_INFO_MODE;
|
||||
}
|
||||
|
||||
function detectLayoutMode() {
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
@@ -794,7 +808,9 @@ function getCurrentSharedSettingsSnapshot() {
|
||||
motionDebugSkeletonOnly,
|
||||
mediaPanelActiveTab: normalizeMediaPanelActiveTab(getActiveTVTab()),
|
||||
satelliteIdleBreathingEnabled: getSatelliteIdleBreathingEnabled(),
|
||||
satelliteRealAltitudeEnabled: getSatelliteRealAltitudeEnabled(),
|
||||
interactableCompactDotsEnabled: getInteractableCompactDotsEnabled(),
|
||||
surfaceHoverInfoMode: getSurfaceHoverInfoMode(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -848,8 +864,13 @@ function cloneEarthSettings(settings) {
|
||||
mediaPanelActiveTab: normalizeMediaPanelActiveTab(settings.shared.mediaPanelActiveTab),
|
||||
satelliteIdleBreathingEnabled:
|
||||
settings.shared.satelliteIdleBreathingEnabled !== false,
|
||||
satelliteRealAltitudeEnabled:
|
||||
settings.shared.satelliteRealAltitudeEnabled !== false,
|
||||
interactableCompactDotsEnabled:
|
||||
settings.shared.interactableCompactDotsEnabled !== false,
|
||||
surfaceHoverInfoMode: normalizeSurfaceHoverInfoMode(
|
||||
settings.shared.surfaceHoverInfoMode,
|
||||
),
|
||||
layerVisibility: { ...(settings.shared.layerVisibility || {}) },
|
||||
},
|
||||
views: {
|
||||
@@ -975,11 +996,19 @@ function normalizeEarthSettings(rawSettings, defaults) {
|
||||
typeof sharedSettings?.satelliteIdleBreathingEnabled === "boolean"
|
||||
? sharedSettings.satelliteIdleBreathingEnabled
|
||||
: defaults.shared.satelliteIdleBreathingEnabled;
|
||||
const nextSatelliteRealAltitudeEnabled =
|
||||
typeof sharedSettings?.satelliteRealAltitudeEnabled === "boolean"
|
||||
? sharedSettings.satelliteRealAltitudeEnabled
|
||||
: defaults.shared.satelliteRealAltitudeEnabled;
|
||||
const nextInteractableCompactDotsEnabled =
|
||||
(rawSettings?.version || 0) >= VISUAL_PREFERENCES_DEFAULT_VERSION &&
|
||||
typeof sharedSettings?.interactableCompactDotsEnabled === "boolean"
|
||||
? sharedSettings.interactableCompactDotsEnabled
|
||||
: defaults.shared.interactableCompactDotsEnabled;
|
||||
const nextSurfaceHoverInfoMode =
|
||||
(rawSettings?.version || 0) >= SURFACE_HOVER_INFO_DEFAULT_VERSION
|
||||
? normalizeSurfaceHoverInfoMode(sharedSettings?.surfaceHoverInfoMode)
|
||||
: defaults.shared.surfaceHoverInfoMode;
|
||||
const nextTrailsEnabled = typeof sharedSettings?.trailsEnabled === "boolean"
|
||||
? sharedSettings.trailsEnabled
|
||||
: typeof inputLayerVisibility.trails === "boolean"
|
||||
@@ -1006,7 +1035,9 @@ function normalizeEarthSettings(rawSettings, defaults) {
|
||||
motionDebugSkeletonOnly: nextMotionDebugSkeletonOnly,
|
||||
mediaPanelActiveTab: nextMediaPanelActiveTab,
|
||||
satelliteIdleBreathingEnabled: nextSatelliteIdleBreathingEnabled,
|
||||
satelliteRealAltitudeEnabled: nextSatelliteRealAltitudeEnabled,
|
||||
interactableCompactDotsEnabled: nextInteractableCompactDotsEnabled,
|
||||
surfaceHoverInfoMode: nextSurfaceHoverInfoMode,
|
||||
},
|
||||
views: {
|
||||
desktop: {
|
||||
@@ -1195,6 +1226,15 @@ function syncSatelliteIdleBreathingToggle() {
|
||||
});
|
||||
}
|
||||
|
||||
function syncSatelliteRealAltitudeToggle() {
|
||||
const enabled = getSatelliteRealAltitudeEnabled();
|
||||
document.querySelectorAll("[data-satellite-real-altitude-toggle]").forEach((input) => {
|
||||
if (input instanceof HTMLInputElement) {
|
||||
input.checked = enabled;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function syncInteractableCompactDotsToggle() {
|
||||
const enabled = getInteractableCompactDotsEnabled();
|
||||
document.querySelectorAll("[data-interactable-compact-dots-toggle]").forEach((input) => {
|
||||
@@ -1294,6 +1334,27 @@ export function setSatelliteIdleBreathingEnabled(
|
||||
return enabled;
|
||||
}
|
||||
|
||||
export function setSatelliteRealAltitudeEnabled(
|
||||
nextEnabled,
|
||||
{ persist = true, suppressStatus = false } = {},
|
||||
) {
|
||||
const enabled = applySatelliteRealAltitudeEnabled(nextEnabled);
|
||||
ensureMutableEarthSettingsState();
|
||||
earthSettingsState.shared.satelliteRealAltitudeEnabled = enabled;
|
||||
syncSatelliteRealAltitudeToggle();
|
||||
|
||||
if (persist) {
|
||||
persistEarthSettings();
|
||||
}
|
||||
if (!suppressStatus) {
|
||||
showStatusMessage(
|
||||
enabled ? "卫星真实高度已开启" : "卫星已切换为旧版同层高度",
|
||||
"info",
|
||||
);
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
export function setInteractableCompactDotsEnabled(
|
||||
nextEnabled,
|
||||
{ persist = true, suppressStatus = false } = {},
|
||||
@@ -1387,6 +1448,10 @@ async function applyEarthSettings(settings, { applyLayers = true } = {}) {
|
||||
persist: false,
|
||||
suppressStatus: true,
|
||||
});
|
||||
setSatelliteRealAltitudeEnabled(settings.shared.satelliteRealAltitudeEnabled, {
|
||||
persist: false,
|
||||
suppressStatus: true,
|
||||
});
|
||||
setInteractableCompactDotsEnabled(settings.shared.interactableCompactDotsEnabled, {
|
||||
persist: false,
|
||||
suppressStatus: true,
|
||||
@@ -2714,6 +2779,13 @@ function setupSettingsControls() {
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-satellite-real-altitude-toggle]").forEach((toggle) => {
|
||||
if (!(toggle instanceof HTMLInputElement)) return;
|
||||
bindListener(toggle, "change", () => {
|
||||
setSatelliteRealAltitudeEnabled(toggle.checked);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-trails-toggle]").forEach((toggle) => {
|
||||
if (!(toggle instanceof HTMLInputElement)) return;
|
||||
bindListener(toggle, "change", () => {
|
||||
@@ -2767,6 +2839,9 @@ function setupSettingsControls() {
|
||||
syncRotationModeButtons();
|
||||
syncCruiseModuleControls();
|
||||
syncSatelliteDisplayStyleControls();
|
||||
syncSatelliteIdleBreathingToggle();
|
||||
syncSatelliteRealAltitudeToggle();
|
||||
syncInteractableCompactDotsToggle();
|
||||
syncDayNightToggle(dayNightEnabled);
|
||||
syncMotionDebugToggle(motionDebugEnabled);
|
||||
syncMotionProviderControls(motionProvider);
|
||||
|
||||
@@ -43,6 +43,7 @@ let satelliteCapacity = 0;
|
||||
let satelliteSatrecCache = new Map();
|
||||
let satelliteDisplayStyle = DEFAULT_SATELLITE_DISPLAY_STYLE;
|
||||
let satelliteIdleBreathingEnabled = true;
|
||||
let satelliteRealAltitudeEnabled = true;
|
||||
|
||||
const GROUND_FOOTPRINT_RENDER_ORDER = 3;
|
||||
|
||||
@@ -338,6 +339,28 @@ export function setSatelliteIdleBreathingEnabled(enabled) {
|
||||
return satelliteIdleBreathingEnabled;
|
||||
}
|
||||
|
||||
export function getSatelliteRealAltitudeEnabled() {
|
||||
return satelliteRealAltitudeEnabled;
|
||||
}
|
||||
|
||||
export function setSatelliteRealAltitudeEnabled(enabled) {
|
||||
const nextEnabled = Boolean(enabled);
|
||||
if (nextEnabled === satelliteRealAltitudeEnabled) {
|
||||
return satelliteRealAltitudeEnabled;
|
||||
}
|
||||
|
||||
satelliteRealAltitudeEnabled = nextEnabled;
|
||||
clearSatelliteTrails();
|
||||
updateSatellitePositions(0, true, { resetTrails: true });
|
||||
if (
|
||||
lockedSatelliteIndex !== null &&
|
||||
satellitePositions?.[lockedSatelliteIndex]?.current
|
||||
) {
|
||||
showHoverRing(satellitePositions[lockedSatelliteIndex].current, true);
|
||||
}
|
||||
return satelliteRealAltitudeEnabled;
|
||||
}
|
||||
|
||||
export function updateSatelliteIdleBreathingVisual(isIdle = true) {
|
||||
if (!satellitePoints || !satelliteBackdropPoints) return;
|
||||
|
||||
@@ -940,8 +963,13 @@ function computeSatellitePosition(satellite, time) {
|
||||
}
|
||||
|
||||
const r = Math.sqrt(x * x + y * y + z * z);
|
||||
const displayRadius =
|
||||
CONFIG.earthRadius + SATELLITE_CONFIG.displayAltitudeOffset;
|
||||
if (!Number.isFinite(r) || r <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const displayRadius = satelliteRealAltitudeEnabled
|
||||
? CONFIG.earthRadius + getCompressedRealAltitudeOffset(r)
|
||||
: CONFIG.earthRadius + SATELLITE_CONFIG.fallbackAltitudeOffset;
|
||||
const scale = displayRadius / r;
|
||||
|
||||
return new THREE.Vector3(x * scale, y * scale, z * scale);
|
||||
@@ -950,6 +978,23 @@ function computeSatellitePosition(satellite, time) {
|
||||
}
|
||||
}
|
||||
|
||||
function getCompressedRealAltitudeOffset(radiusKm) {
|
||||
const altitudeKm = Math.max(0, radiusKm - EARTH_RADIUS_KM);
|
||||
const clampedAltitudeKm = Math.min(
|
||||
altitudeKm,
|
||||
SATELLITE_CONFIG.maxDisplayAltitudeKm,
|
||||
);
|
||||
const compressionKm = Math.max(1, SATELLITE_CONFIG.altitudeCompressionKm);
|
||||
const normalizedAltitude = Math.log1p(clampedAltitudeKm / compressionKm) /
|
||||
Math.log1p(SATELLITE_CONFIG.maxDisplayAltitudeKm / compressionKm);
|
||||
|
||||
return THREE.MathUtils.lerp(
|
||||
SATELLITE_CONFIG.minRealAltitudeOffset,
|
||||
SATELLITE_CONFIG.maxRealAltitudeOffset,
|
||||
THREE.MathUtils.clamp(normalizedAltitude, 0, 1),
|
||||
);
|
||||
}
|
||||
|
||||
function buildSatrecFromProperties(props, fallbackTime) {
|
||||
if (props.tle_line1 && props.tle_line2) {
|
||||
// Prefer source-provided TLE lines so the client does not need to rebuild them.
|
||||
@@ -1088,7 +1133,7 @@ function buildTleLinesFromElements(props, fallbackTime) {
|
||||
}
|
||||
|
||||
function generateFallbackPosition(satellite, index, total, time = new Date()) {
|
||||
const radius = CONFIG.earthRadius + SATELLITE_CONFIG.displayAltitudeOffset;
|
||||
const radius = CONFIG.earthRadius + SATELLITE_CONFIG.fallbackAltitudeOffset;
|
||||
|
||||
const noradId = satellite.properties?.norad_cat_id || index;
|
||||
const inclination = satellite.properties?.inclination || 53;
|
||||
@@ -2557,7 +2602,7 @@ function calculatePredictedOrbit(
|
||||
if (points.length < samples * 0.5) {
|
||||
points.length = 0;
|
||||
const radius =
|
||||
CONFIG.earthRadius + SATELLITE_CONFIG.displayAltitudeOffset;
|
||||
CONFIG.earthRadius + SATELLITE_CONFIG.fallbackAltitudeOffset;
|
||||
const inclination = satellite.properties?.inclination || 53;
|
||||
const raan = satellite.properties?.raan || 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user