98 lines
3.8 KiB
JavaScript
98 lines
3.8 KiB
JavaScript
/**
|
||
* 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);
|
||
};
|
||
|
||
}());
|