fix: refine earth hud structure and bun startup flow
- refactor the /earth HUD into class-first CSS layers with dedicated base, hud, and toolbar responsibilities - clean up Earth markup and runtime DOM hooks so shared panel, toolbar, tooltip, and status classes stay consistent after dynamic updates - keep HUD scaling configurable through extracted constants and remove leftover legacy panel/toolbar styling paths - make planet.sh self-bootstrap Bun and uv by prepending local runtime bins to PATH and auto-installing missing tools in fresh environments - document Bun as the frontend package manager of record and sync repository version metadata to 0.24.1
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { createNoise3D } from "simplex-noise";
|
||||
|
||||
import { CONFIG, CABLE_CONFIG, CABLE_STATE } from "./constants.js";
|
||||
import { CONFIG, HUD_CONFIG, CABLE_CONFIG, CABLE_STATE } from "./constants.js";
|
||||
import { vector3ToLatLon, screenToEarthCoords } from "./utils.js";
|
||||
import {
|
||||
showStatusMessage,
|
||||
@@ -174,6 +174,7 @@ const cleanupFns = [];
|
||||
const DRAG_SMOOTHING_FACTOR = 0.18;
|
||||
const INERTIA_DAMPING = 0.92;
|
||||
const INERTIA_MIN_VELOCITY = 0.00008;
|
||||
const ACTIVE_BGP_TOOLTIP_TEXT = "隐藏BGP观测";
|
||||
const HUD_INTERACTIVE_SELECTORS = [
|
||||
"#info-panel",
|
||||
"#info-panel *",
|
||||
@@ -195,6 +196,17 @@ function bindListener(target, eventName, handler, options) {
|
||||
);
|
||||
}
|
||||
|
||||
function getViewportAspect() {
|
||||
return window.innerWidth / window.innerHeight;
|
||||
}
|
||||
|
||||
function syncRendererViewport() {
|
||||
if (!camera || !renderer) return;
|
||||
camera.aspect = getViewportAspect();
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
function isEventOnHud(event) {
|
||||
const target = event?.target;
|
||||
if (!(target instanceof Element)) return false;
|
||||
@@ -520,6 +532,47 @@ function showBGPCollectorInfo(marker) {
|
||||
});
|
||||
}
|
||||
|
||||
function getBGPStatusText(bgpResult) {
|
||||
if (bgpResult.totalCount > 0) {
|
||||
return `${bgpResult.totalCount} 起活跃事件`;
|
||||
}
|
||||
if (bgpResult.anomalyCount > 0) {
|
||||
return `${bgpResult.anomalyCount} 条活跃异常`;
|
||||
}
|
||||
return "当前无活跃事件";
|
||||
}
|
||||
|
||||
function updateBGPHud(bgpResult) {
|
||||
const bgpBtn = document.getElementById("toggle-bgp");
|
||||
if (bgpBtn) {
|
||||
bgpBtn.classList.add("active");
|
||||
const tooltip = bgpBtn.querySelector(".earth-toolbar-tooltip");
|
||||
if (tooltip) {
|
||||
tooltip.textContent = ACTIVE_BGP_TOOLTIP_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
const bgpCountEl = document.getElementById("bgp-anomaly-count");
|
||||
if (bgpCountEl) {
|
||||
bgpCountEl.textContent = `${bgpResult.totalCount} 起`;
|
||||
}
|
||||
|
||||
const bgpCollectorEl = document.getElementById("bgp-collector-count");
|
||||
if (bgpCollectorEl) {
|
||||
bgpCollectorEl.textContent = `${bgpResult.collectorCount} 个`;
|
||||
}
|
||||
|
||||
const bgpStatusEl = document.getElementById("bgp-status-summary");
|
||||
if (bgpStatusEl) {
|
||||
bgpStatusEl.textContent = getBGPStatusText(bgpResult);
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelectionAndInfo() {
|
||||
clearLockedObject();
|
||||
hideInfoCard();
|
||||
}
|
||||
|
||||
function getBGPRelatedCableNames(marker) {
|
||||
const items = Array.isArray(marker?.userData?.related_cables)
|
||||
? marker.userData.related_cables
|
||||
@@ -655,7 +708,7 @@ function updateSatelliteToggleUi(enabled, satelliteCount = getSatelliteCount())
|
||||
const satBtn = document.getElementById("toggle-satellites");
|
||||
if (satBtn) {
|
||||
satBtn.classList.toggle("active", enabled);
|
||||
const tooltip = satBtn.querySelector(".tooltip");
|
||||
const tooltip = satBtn.querySelector(".earth-toolbar-tooltip");
|
||||
if (tooltip) tooltip.textContent = enabled ? "隐藏卫星" : "显示卫星";
|
||||
}
|
||||
|
||||
@@ -669,7 +722,7 @@ function updateCableToggleUi(enabled) {
|
||||
const cableBtn = document.getElementById("toggle-cables");
|
||||
if (cableBtn) {
|
||||
cableBtn.classList.toggle("active", enabled);
|
||||
const tooltip = cableBtn.querySelector(".tooltip");
|
||||
const tooltip = cableBtn.querySelector(".earth-toolbar-tooltip");
|
||||
if (tooltip) tooltip.textContent = enabled ? "隐藏线缆" : "显示线缆";
|
||||
}
|
||||
|
||||
@@ -799,11 +852,12 @@ export function init() {
|
||||
destroyed = false;
|
||||
initialized = true;
|
||||
simplex = createNoise3D();
|
||||
updateHudScale();
|
||||
|
||||
scene = new THREE.Scene();
|
||||
camera = new THREE.PerspectiveCamera(
|
||||
75,
|
||||
window.innerWidth / window.innerHeight,
|
||||
getViewportAspect(),
|
||||
0.1,
|
||||
1000,
|
||||
);
|
||||
@@ -815,7 +869,7 @@ export function init() {
|
||||
alpha: false,
|
||||
powerPreference: "high-performance",
|
||||
});
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
syncRendererViewport();
|
||||
renderer.setClearColor(0x0a0a1a, 1);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
|
||||
@@ -898,8 +952,7 @@ async function loadData(showWhiteSphere = false) {
|
||||
: "同步卫星、海底光缆、登陆点与BGP态势数据",
|
||||
);
|
||||
setLoading(true);
|
||||
clearLockedObject();
|
||||
hideInfoCard();
|
||||
clearSelectionAndInfo();
|
||||
|
||||
if (showWhiteSphere && earth.material) {
|
||||
earthTexture = earth.material.map;
|
||||
@@ -915,29 +968,7 @@ async function loadData(showWhiteSphere = false) {
|
||||
clearBGPData(earth);
|
||||
const bgpResult = await loadBGPAnomalies(scene, earth);
|
||||
toggleBGP(true);
|
||||
const bgpBtn = document.getElementById("toggle-bgp");
|
||||
if (bgpBtn) {
|
||||
bgpBtn.classList.add("active");
|
||||
const tooltip = bgpBtn.querySelector(".tooltip");
|
||||
if (tooltip) tooltip.textContent = "隐藏BGP观测";
|
||||
}
|
||||
const bgpCountEl = document.getElementById("bgp-anomaly-count");
|
||||
if (bgpCountEl) {
|
||||
bgpCountEl.textContent = `${bgpResult.totalCount} 起`;
|
||||
}
|
||||
const bgpCollectorEl = document.getElementById("bgp-collector-count");
|
||||
if (bgpCollectorEl) {
|
||||
bgpCollectorEl.textContent = `${bgpResult.collectorCount} 个`;
|
||||
}
|
||||
const bgpStatusEl = document.getElementById("bgp-status-summary");
|
||||
if (bgpStatusEl) {
|
||||
bgpStatusEl.textContent =
|
||||
bgpResult.totalCount > 0
|
||||
? `${bgpResult.totalCount} 起活跃事件`
|
||||
: bgpResult.anomalyCount > 0
|
||||
? `${bgpResult.anomalyCount} 条活跃异常`
|
||||
: "当前无活跃事件";
|
||||
}
|
||||
updateBGPHud(bgpResult);
|
||||
return bgpResult;
|
||||
})(),
|
||||
]);
|
||||
@@ -997,8 +1028,7 @@ export async function setCablesEnabled(enabled) {
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
clearLockedObject();
|
||||
hideInfoCard();
|
||||
clearSelectionAndInfo();
|
||||
disableCables();
|
||||
showStatusMessage("线缆已隐藏", "info");
|
||||
return 0;
|
||||
@@ -1032,8 +1062,7 @@ export async function setSatellitesEnabled(enabled) {
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
clearLockedObject();
|
||||
hideInfoCard();
|
||||
clearSelectionAndInfo();
|
||||
disableSatellites();
|
||||
return 0;
|
||||
}
|
||||
@@ -1078,11 +1107,24 @@ function setupEventListeners() {
|
||||
bindListener(renderer.domElement, "click", handleClick);
|
||||
}
|
||||
|
||||
function updateHudScale() {
|
||||
const widthScale = window.innerWidth / HUD_CONFIG.scaleReferenceWidth;
|
||||
const heightScale = window.innerHeight / HUD_CONFIG.scaleReferenceHeight;
|
||||
const nextScale = THREE.MathUtils.clamp(
|
||||
Math.min(widthScale, heightScale),
|
||||
HUD_CONFIG.minScale,
|
||||
HUD_CONFIG.maxScale,
|
||||
);
|
||||
|
||||
document.documentElement.style.setProperty(
|
||||
"--hud-scale",
|
||||
nextScale.toFixed(3),
|
||||
);
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
if (!camera || !renderer) return;
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
updateHudScale();
|
||||
syncRendererViewport();
|
||||
}
|
||||
|
||||
function getFrontFacingCables(cableLines) {
|
||||
|
||||
Reference in New Issue
Block a user