fix: refine earth settings modal and hud interactions
This commit is contained in:
177
frontend/public/earth/js/controls.js
vendored
177
frontend/public/earth/js/controls.js
vendored
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user