/** * plugin-ui.js – Layer-Steuerung (ein-/ausblenden) * ==================================================== * Abhängigkeit: earth-core.js */ (function () { const LAYERS = [ { name: "Nacht & Dämmerung", canvasIds: ["nightCanvas", "terminatorCanvas"], defaultOn: true }, { name: "Wolken", canvasIds: ["cloudCanvas"], defaultOn: false }, { name: "Aurora", canvasIds: ["auroraCanvas"], defaultOn: false }, { name: "Satelliten", canvasIds: ["orbitCanvas"], defaultOn: true }, { name: "Sonne", canvasIds: ["sunCanvas"], defaultOn: true }, { name: "Mond", canvasIds: ["moonCanvas"], defaultOn: true }, { name: "Erdbeben", canvasIds: ["earthquakeCanvas"], defaultOn: false }, { name: "Ortsmarker", canvasIds: ["markersCanvas"], defaultOn: false }, ]; const CFG = { TITLE: "Layer", ACCENT: "#4a9eff", ACCENT_OFF: "rgba(50, 60, 90, 0.9)", }; // ── pendingVisibility und setVisibility VOR dem UI-Aufbau ────── const pendingVisibility = new Map(); function setVisibility(layer, on) { layer.canvasIds.forEach(id => { const el = document.getElementById(id); if (el) { el.style.display = on ? "block" : "none"; } else { pendingVisibility.set(id, on); } }); } const observer = new MutationObserver(mutations => { for (const mut of mutations) { for (const node of mut.addedNodes) { if (node.id && pendingVisibility.has(node.id)) { node.style.display = pendingVisibility.get(node.id) ? "block" : "none"; pendingVisibility.delete(node.id); } } } if (pendingVisibility.size === 0) observer.disconnect(); }); observer.observe(document.getElementById("earth-wrapper") || document.body, { childList: true, subtree: true, }); // ── CSS ──────────────────────────────────────────────────────── const style = document.createElement("style"); style.textContent = ` #earth-ui { position: absolute; bottom: 14px; left: 14px; z-index: 9999; background: rgba(6, 10, 22, 0.78); border: 1px solid rgba(80, 110, 190, 0.28); border-radius: 8px; padding: 7px 10px; font: 11px/1.4 system-ui, -apple-system, sans-serif; color: rgba(190, 210, 255, 0.88); user-select: none; min-width: 140px; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: 0 2px 16px rgba(0,0,0,0.5); opacity: 0.75; transition: opacity 0.2s; } #earth-ui:hover { opacity: 1; } #earth-ui-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; cursor: pointer; gap: 8px; } #earth-ui-title { font-weight: 600; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(140, 170, 255, 0.75); } #earth-ui-chevron { font-size: 8px; color: rgba(100, 120, 180, 0.6); transition: transform 0.2s; } #earth-ui-chevron.collapsed { transform: rotate(-90deg); } #earth-ui-rows { display: flex; flex-direction: column; gap: 4px; overflow: hidden; max-height: 300px; opacity: 1; transition: max-height 0.2s ease, opacity 0.15s; } #earth-ui-rows.collapsed { max-height: 0; opacity: 0; } .earth-ui-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .earth-ui-label { font-size: 11px; color: rgba(190, 210, 255, 0.85); transition: color 0.15s; flex: 1; cursor: pointer; } .earth-ui-label:hover { color: #fff; } .earth-ui-label.off { color: rgba(100, 115, 155, 0.65); } /* Schmaler Toggle: 28×15px */ .earth-ui-toggle { position: relative; width: 28px; height: 15px; flex-shrink: 0; } .earth-ui-toggle input { opacity: 0; width: 0; height: 0; position: absolute; } .earth-ui-slider { position: absolute; inset: 0; border-radius: 15px; background: ${CFG.ACCENT_OFF}; transition: background 0.18s; cursor: pointer; } .earth-ui-slider::before { content: ""; position: absolute; width: 10px; height: 10px; left: 2.5px; top: 50%; transform: translateY(-50%); border-radius: 50%; background: rgba(160, 175, 210, 0.8); transition: left 0.18s, background 0.18s; } .earth-ui-toggle input:checked + .earth-ui-slider { background: ${CFG.ACCENT}; } .earth-ui-toggle input:checked + .earth-ui-slider::before { left: 15.5px; background: #fff; } `; document.head.appendChild(style); // ── Panel ────────────────────────────────────────────────────── const panel = document.createElement("div"); panel.id = "earth-ui"; const header = document.createElement("div"); header.id = "earth-ui-header"; header.innerHTML = ` ${CFG.TITLE} ▼ `; panel.appendChild(header); const rows = document.createElement("div"); rows.id = "earth-ui-rows"; panel.appendChild(rows); let collapsed = false; header.addEventListener("click", () => { collapsed = !collapsed; rows.classList.toggle("collapsed", collapsed); document.getElementById("earth-ui-chevron").classList.toggle("collapsed", collapsed); }); // ── Rows ─────────────────────────────────────────────────────── LAYERS.forEach(layer => { const row = document.createElement("div"); row.className = "earth-ui-row"; const label = document.createElement("span"); label.className = "earth-ui-label"; label.textContent = layer.name; const toggleWrap = document.createElement("label"); toggleWrap.className = "earth-ui-toggle"; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.checked = layer.defaultOn; const slider = document.createElement("span"); slider.className = "earth-ui-slider"; toggleWrap.appendChild(checkbox); toggleWrap.appendChild(slider); row.appendChild(label); row.appendChild(toggleWrap); rows.appendChild(row); setVisibility(layer, layer.defaultOn); if (!layer.defaultOn) label.classList.add("off"); checkbox.addEventListener("change", () => { setVisibility(layer, checkbox.checked); label.classList.toggle("off", !checkbox.checked); }); label.addEventListener("click", () => { checkbox.checked = !checkbox.checked; checkbox.dispatchEvent(new Event("change")); }); }); (document.getElementById("earth-wrapper") || document.body).appendChild(panel); }());