/** * plugin-clouds.js – Wolken-Layer * ================================== * Abhängigkeit: earth-core.js, plugin-terminator.js * * Erstellt: #cloudCanvas (z-index 3) * * Lauscht auf earth:terminator und zeichnet die Wolkentextur * mit getrennter Deckkraft für Tag- und Nachtseite. */ (function () { // ═══════════════════════════════════════════════════════════════ // KONFIGURATION // ═══════════════════════════════════════════════════════════════ const CFG = { // Externe Wolkentextur (Alpha-PNG) CLOUD_URL: "https://clouds.matteason.co.uk/images/2048x1024/clouds-alpha.png", // Deckkraft der Wolken (0.0 = unsichtbar | 1.0 = voll sichtbar) CLOUD_ALPHA_DAY: 0.35, // Tagseite CLOUD_ALPHA_NIGHT: 0.18, // Nachtseite }; // ── Kurz-Referenz auf EarthCore-Helfer ──────────────────────── const { toX, toY, createCanvas, syncCanvas } = EarthCore; // ── Canvas & Context ────────────────────────────────────────── const cloudCanvas = createCanvas("cloudCanvas", 3); const ctx = cloudCanvas.getContext("2d"); // ── Wolkenbild laden ────────────────────────────────────────── const cloudImg = new Image(); cloudImg.crossOrigin = "anonymous"; cloudImg.src = CFG.CLOUD_URL; // Letzter bekannter Terminator-State (für Re-Renders bei Resize) let _lastTerminator = null; // ═══════════════════════════════════════════════════════════════ // ZEICHNEN // ═══════════════════════════════════════════════════════════════ function clipToSide(pts, w, h, northIsNight, nightSide) { ctx.beginPath(); if (!nightSide) ctx.rect(0, 0, w, h); ctx.moveTo(toX(pts[0].lon, w), toY(pts[0].lat, h)); for (let i = 1; i < pts.length; i++) { ctx.lineTo(toX(pts[i].lon, w), toY(pts[i].lat, h)); } if (northIsNight) { ctx.lineTo(w, 0); ctx.lineTo(0, 0); } else { ctx.lineTo(w, h); ctx.lineTo(0, h); } ctx.closePath(); ctx.clip(nightSide ? "nonzero" : "evenodd"); } function render({ pts, northIsNight, w, h }) { if (!cloudImg.complete || !cloudImg.naturalWidth) return; if (!w || !h) return; syncCanvas(cloudCanvas, w, h); ctx.clearRect(0, 0, w, h); // Tagseite ctx.save(); clipToSide(pts, w, h, northIsNight, false); ctx.globalAlpha = CFG.CLOUD_ALPHA_DAY; ctx.drawImage(cloudImg, 0, 0, w, h); ctx.restore(); // Nachtseite ctx.save(); clipToSide(pts, w, h, northIsNight, true); ctx.globalAlpha = CFG.CLOUD_ALPHA_NIGHT; ctx.drawImage(cloudImg, 0, 0, w, h); ctx.restore(); } // ── Events ──────────────────────────────────────────────────── window.addEventListener("earth:terminator", e => { _lastTerminator = e.detail; render(e.detail); }); window.addEventListener("earth:resize", e => { if (_lastTerminator) { render({ ..._lastTerminator, w: e.detail.w, h: e.detail.h }); } }); cloudImg.onload = () => { if (_lastTerminator) render(_lastTerminator); }; }());