fix: redesign earth hud interactions and legend behavior
This commit is contained in:
135
frontend/public/earth/js/controls.js
vendored
135
frontend/public/earth/js/controls.js
vendored
@@ -16,6 +16,7 @@ export let autoRotate = true;
|
||||
export let zoomLevel = 1.0;
|
||||
export let showTerrain = false;
|
||||
export let isDragging = false;
|
||||
export let layoutExpanded = false;
|
||||
|
||||
let earthObj = null;
|
||||
let listeners = [];
|
||||
@@ -43,6 +44,7 @@ export function setupControls(camera, renderer, scene, earth) {
|
||||
setupWheelZoom(camera, renderer);
|
||||
setupRotateControls(camera, earth);
|
||||
setupTerrainControls();
|
||||
setupLiquidGlassInteractions();
|
||||
}
|
||||
|
||||
function setupZoomControls(camera) {
|
||||
@@ -285,13 +287,18 @@ function setupRotateControls(camera) {
|
||||
}
|
||||
|
||||
function setupTerrainControls() {
|
||||
const container = document.getElementById("container");
|
||||
const searchBtn = document.getElementById("search-action");
|
||||
const infoGroup = document.getElementById("info-control-group");
|
||||
const infoTrigger = document.getElementById("info-trigger");
|
||||
const terrainBtn = document.getElementById("toggle-terrain");
|
||||
const satellitesBtn = document.getElementById("toggle-satellites");
|
||||
const trailsBtn = document.getElementById("toggle-trails");
|
||||
const cablesBtn = document.getElementById("toggle-cables");
|
||||
const layoutBtn = document.getElementById("layout-toggle");
|
||||
const reloadBtn = document.getElementById("reload-data");
|
||||
const toolbarToggle = document.getElementById("toolbar-toggle");
|
||||
const toolbar = document.getElementById("control-toolbar");
|
||||
const zoomGroup = document.getElementById("zoom-control-group");
|
||||
const zoomTrigger = document.getElementById("zoom-trigger");
|
||||
|
||||
if (trailsBtn) {
|
||||
trailsBtn.classList.add("active");
|
||||
@@ -299,6 +306,10 @@ function setupTerrainControls() {
|
||||
if (tooltip) tooltip.textContent = "隐藏轨迹";
|
||||
}
|
||||
|
||||
bindListener(searchBtn, "click", () => {
|
||||
showStatusMessage("搜索功能待开发", "info");
|
||||
});
|
||||
|
||||
bindListener(terrainBtn, "click", function () {
|
||||
showTerrain = !showTerrain;
|
||||
toggleTerrain(showTerrain);
|
||||
@@ -352,11 +363,102 @@ function setupTerrainControls() {
|
||||
await reloadData();
|
||||
});
|
||||
|
||||
if (toolbarToggle && toolbar) {
|
||||
bindListener(toolbarToggle, "click", () => {
|
||||
toolbar.classList.toggle("collapsed");
|
||||
bindListener(zoomTrigger, "click", (event) => {
|
||||
event.stopPropagation();
|
||||
infoGroup?.classList.remove("open");
|
||||
zoomGroup?.classList.toggle("open");
|
||||
});
|
||||
|
||||
bindListener(zoomGroup, "click", (event) => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
bindListener(infoTrigger, "click", (event) => {
|
||||
event.stopPropagation();
|
||||
zoomGroup?.classList.remove("open");
|
||||
infoGroup?.classList.toggle("open");
|
||||
});
|
||||
|
||||
bindListener(infoGroup, "click", (event) => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
bindListener(document, "click", (event) => {
|
||||
if (zoomGroup?.classList.contains("open")) {
|
||||
if (!zoomGroup.contains(event.target)) {
|
||||
zoomGroup.classList.remove("open");
|
||||
}
|
||||
}
|
||||
if (infoGroup?.classList.contains("open")) {
|
||||
if (!infoGroup.contains(event.target)) {
|
||||
infoGroup.classList.remove("open");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bindListener(layoutBtn, "click", () => {
|
||||
const expanded = toggleLayoutExpanded(container);
|
||||
showStatusMessage(expanded ? "布局已最大化" : "布局已恢复", "info");
|
||||
});
|
||||
|
||||
updateLayoutUI(container);
|
||||
}
|
||||
|
||||
function setupLiquidGlassInteractions() {
|
||||
const surfaces = document.querySelectorAll(".liquid-glass-surface");
|
||||
|
||||
const resetSurface = (surface) => {
|
||||
surface.style.setProperty("--elastic-x", "0px");
|
||||
surface.style.setProperty("--elastic-y", "0px");
|
||||
surface.style.setProperty("--tilt-x", "0deg");
|
||||
surface.style.setProperty("--tilt-y", "0deg");
|
||||
surface.style.setProperty("--glow-x", "50%");
|
||||
surface.style.setProperty("--glow-y", "22%");
|
||||
surface.style.setProperty("--glow-opacity", "0.24");
|
||||
surface.classList.remove("is-pressed");
|
||||
};
|
||||
|
||||
surfaces.forEach((surface) => {
|
||||
resetSurface(surface);
|
||||
|
||||
bindListener(surface, "pointermove", (event) => {
|
||||
const rect = surface.getBoundingClientRect();
|
||||
const px = (event.clientX - rect.left) / rect.width;
|
||||
const py = (event.clientY - rect.top) / rect.height;
|
||||
const offsetX = (px - 0.5) * 6;
|
||||
const offsetY = (py - 0.5) * 6;
|
||||
const tiltX = (0.5 - py) * 8;
|
||||
const tiltY = (px - 0.5) * 10;
|
||||
|
||||
surface.style.setProperty("--elastic-x", `${offsetX.toFixed(2)}px`);
|
||||
surface.style.setProperty("--elastic-y", `${offsetY.toFixed(2)}px`);
|
||||
surface.style.setProperty("--tilt-x", `${tiltX.toFixed(2)}deg`);
|
||||
surface.style.setProperty("--tilt-y", `${tiltY.toFixed(2)}deg`);
|
||||
surface.style.setProperty("--glow-x", `${(px * 100).toFixed(1)}%`);
|
||||
surface.style.setProperty("--glow-y", `${(py * 100).toFixed(1)}%`);
|
||||
surface.style.setProperty("--glow-opacity", "0.34");
|
||||
});
|
||||
}
|
||||
|
||||
bindListener(surface, "pointerenter", () => {
|
||||
surface.style.setProperty("--glow-opacity", "0.28");
|
||||
});
|
||||
|
||||
bindListener(surface, "pointerleave", () => {
|
||||
resetSurface(surface);
|
||||
});
|
||||
|
||||
bindListener(surface, "pointerdown", () => {
|
||||
surface.classList.add("is-pressed");
|
||||
});
|
||||
|
||||
bindListener(surface, "pointerup", () => {
|
||||
surface.classList.remove("is-pressed");
|
||||
});
|
||||
|
||||
bindListener(surface, "pointercancel", () => {
|
||||
resetSurface(surface);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function teardownControls() {
|
||||
@@ -396,3 +498,24 @@ export function getZoomLevel() {
|
||||
export function getShowTerrain() {
|
||||
return showTerrain;
|
||||
}
|
||||
|
||||
function updateLayoutUI(container) {
|
||||
if (container) {
|
||||
container.classList.toggle("layout-expanded", layoutExpanded);
|
||||
}
|
||||
|
||||
const btn = document.getElementById("layout-toggle");
|
||||
if (btn) {
|
||||
btn.classList.toggle("active", layoutExpanded);
|
||||
const tooltip = btn.querySelector(".tooltip");
|
||||
const nextLabel = layoutExpanded ? "恢复布局" : "最大化布局";
|
||||
btn.title = nextLabel;
|
||||
if (tooltip) tooltip.textContent = nextLabel;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLayoutExpanded(container) {
|
||||
layoutExpanded = !layoutExpanded;
|
||||
updateLayoutUI(container);
|
||||
return layoutExpanded;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user