fix: refine earth settings modal and hud interactions

This commit is contained in:
linkong
2026-04-10 16:37:09 +08:00
committed by rayd1o
parent a2210f0f78
commit e85a9fc614
4 changed files with 528 additions and 10 deletions

View File

@@ -26,6 +26,11 @@ export let layoutExpanded = false;
let earthObj = null;
let listeners = [];
let cleanupFns = [];
const HUD_PANEL_IDS = [
"legend",
"coordinates-display",
"earth-stats",
];
function getFloatingGroups() {
return [
@@ -44,6 +49,12 @@ function isFloatingMenuVisible() {
});
}
function isSettingsModalOpen() {
return document
.getElementById("settings-modal")
?.classList.contains("is-open");
}
function closeFloatingMenus() {
getFloatingGroups().forEach((group) => {
group.classList.remove("open");
@@ -55,6 +66,164 @@ function closeFloatingMenus() {
}
}
function openSettingsModal() {
const modal = document.getElementById("settings-modal");
if (!modal) return;
closeFloatingMenus();
modal.classList.add("is-open");
modal.setAttribute("aria-hidden", "false");
}
function closeSettingsModal() {
const modal = document.getElementById("settings-modal");
if (!modal) return;
modal.classList.remove("is-open");
modal.setAttribute("aria-hidden", "true");
}
function setHudPanelVisibility(panelId, visible) {
const panel = document.getElementById(panelId);
if (!panel) return;
panel.classList.toggle("hud-panel-hidden", !visible);
syncSettingsToggle(panelId, visible);
}
function syncSettingsToggle(panelId, visible) {
const input = document.querySelector(
`[data-settings-panel="${panelId}"]`,
);
if (input instanceof HTMLInputElement) {
input.checked = visible;
}
}
function syncAllHudPanelToggles() {
HUD_PANEL_IDS.forEach((panelId) => {
const panel = document.getElementById(panelId);
syncSettingsToggle(panelId, !panel?.classList.contains("hud-panel-hidden"));
});
}
function setupSettingsControls() {
const settingsTrigger = document.getElementById("settings-trigger");
const settingsClose = document.getElementById("settings-close");
const settingsBackdrop = document.getElementById("settings-backdrop");
const settingsModal = document.getElementById("settings-modal");
bindListener(settingsTrigger, "click", () => {
openSettingsModal();
});
bindListener(settingsClose, "click", () => {
closeSettingsModal();
});
bindListener(settingsBackdrop, "click", () => {
closeSettingsModal();
});
bindListener(settingsModal, "click", (event) => {
const sheet = event.target.closest(".earth-settings-sheet");
if (!sheet) {
closeSettingsModal();
}
});
const toggleInputs = document.querySelectorAll("[data-settings-panel]");
toggleInputs.forEach((input) => {
bindListener(input, "change", (event) => {
const target = event.currentTarget;
if (!(target instanceof HTMLInputElement)) return;
const panelId = target.dataset.settingsPanel;
if (!panelId) return;
setHudPanelVisibility(panelId, target.checked);
});
});
syncAllHudPanelToggles();
}
function setupHudPanelControls() {
const closeButtons = document.querySelectorAll("[data-close-panel]");
closeButtons.forEach((button) => {
bindListener(button, "click", (event) => {
event.stopPropagation();
const target = event.currentTarget;
if (!(target instanceof HTMLElement)) return;
const panelId = target.dataset.closePanel;
if (!panelId) return;
setHudPanelVisibility(panelId, false);
});
});
}
function setupDraggableHudPanels() {
const app = document.getElementById("container");
const draggablePanels = document.querySelectorAll(".hud-panel-draggable");
if (!app || draggablePanels.length === 0) return;
draggablePanels.forEach((panel) => {
const handle = panel.querySelector(".hud-panel-drag-handle");
if (!handle) return;
let isDragging = false;
let startPointerX = 0;
let startPointerY = 0;
let startLeft = 0;
let startTop = 0;
const stopDragging = () => {
isDragging = false;
panel.classList.remove("is-dragging");
document.body.style.userSelect = "";
};
const onMove = (event) => {
if (!isDragging) return;
const appRect = app.getBoundingClientRect();
const panelRect = panel.getBoundingClientRect();
const nextLeft = Math.min(
Math.max(startLeft + (event.clientX - startPointerX), 0),
appRect.width - panelRect.width,
);
const nextTop = Math.min(
Math.max(startTop + (event.clientY - startPointerY), 0),
appRect.height - panelRect.height,
);
panel.style.left = `${nextLeft}px`;
panel.style.top = `${nextTop}px`;
panel.style.right = "auto";
panel.style.bottom = "auto";
panel.style.transform = "none";
};
bindListener(handle, "pointerdown", (event) => {
if (event.target.closest(".hud-panel-close")) return;
isDragging = true;
startPointerX = event.clientX;
startPointerY = event.clientY;
const appRect = app.getBoundingClientRect();
const panelRect = panel.getBoundingClientRect();
startLeft = panelRect.left - appRect.left;
startTop = panelRect.top - appRect.top;
panel.style.left = `${startLeft}px`;
panel.style.top = `${startTop}px`;
panel.style.right = "auto";
panel.style.bottom = "auto";
panel.style.transform = "none";
panel.classList.add("is-dragging");
document.body.style.userSelect = "none";
handle.setPointerCapture?.(event.pointerId);
});
bindListener(handle, "pointermove", onMove);
bindListener(handle, "pointerup", stopDragging);
bindListener(handle, "pointercancel", stopDragging);
bindListener(handle, "lostpointercapture", stopDragging);
});
}
function clearForcedFloatingClose() {
getFloatingGroups().forEach((group) => {
group.classList.remove("force-closed");
@@ -379,6 +548,9 @@ function setupTerrainControls() {
const reloadBtn = document.getElementById("reload-data");
const zoomGroup = document.getElementById("zoom-control-group");
const zoomTrigger = document.getElementById("zoom-trigger");
setupSettingsControls();
setupHudPanelControls();
setupDraggableHudPanels();
if (trailsBtn) {
trailsBtn.classList.add("active");
@@ -487,6 +659,11 @@ function setupKeyboardControls() {
bindListener(document, "keydown", (event) => {
if (event.key !== "Escape") return;
if (isSettingsModalOpen()) {
closeSettingsModal();
return;
}
if (isFloatingMenuVisible()) {
closeFloatingMenus();
return;