diff --git a/public/mondplanetenbedeckungen.php b/public/mondplanetenbedeckungen.php index d259273..0e21105 100644 --- a/public/mondplanetenbedeckungen.php +++ b/public/mondplanetenbedeckungen.php @@ -400,6 +400,13 @@ if (!empty($currentLocation) && is_array($currentLocation)) { uranus: { body: 'Uranus', label: 'Uranus', radiusKm: 25559.0, color: '#8fd9e8' }, neptune: { body: 'Neptune', label: 'Neptun', radiusKm: 24764.0, color: '#5f7fe0' } }; + const MOON_TEXTURE = new Image(); + MOON_TEXTURE.src = 'images/moons/moon4calendar.png'; + MOON_TEXTURE.onload = function () { + if (STATE.selectedEventIndex !== null) { + renderOccultationMap(STATE.selectedEventIndex); + } + }; const OBSERVER = new Astronomy.Observer( Number(SITE_LOCATION.latitude), Number(SITE_LOCATION.longitude), @@ -814,19 +821,11 @@ if (!empty($currentLocation) && is_array($currentLocation)) { }; } - function drawMoonWithTerminator(ctx, centerX, centerY, radiusPx, terminatorInfo) { - const phaseFraction = terminatorInfo.phaseFraction; - const brightSideAngleRad = terminatorInfo.brightSideAngleRad; - const cosPhase = Math.max(-1, Math.min(1, 2 * phaseFraction - 1)); - const isInverted = STATE.invertMap; + function drawMoonWithTerminatorFlat(ctx, radiusPx, phaseFraction, cosPhase, isInverted) { const baseMoonFill = isInverted ? 'rgba(236, 239, 245, 0.98)' : 'rgba(24, 28, 36, 0.96)'; const litMoonFill = isInverted ? 'rgba(86, 94, 112, 0.88)' : 'rgba(228, 232, 240, 0.95)'; const moonStroke = isInverted ? 'rgba(70, 78, 96, 0.75)' : 'rgba(245,248,255,0.72)'; - ctx.save(); - ctx.translate(centerX, centerY); - ctx.rotate(brightSideAngleRad); - ctx.beginPath(); ctx.arc(0, 0, radiusPx, 0, Math.PI * 2); ctx.fillStyle = baseMoonFill; @@ -836,7 +835,6 @@ if (!empty($currentLocation) && is_array($currentLocation)) { ctx.lineWidth = 2; ctx.strokeStyle = isInverted ? 'rgba(70, 78, 96, 0.55)' : 'rgba(170,180,195,0.35)'; ctx.stroke(); - ctx.restore(); return; } @@ -848,7 +846,6 @@ if (!empty($currentLocation) && is_array($currentLocation)) { ctx.lineWidth = 2; ctx.strokeStyle = moonStroke; ctx.stroke(); - ctx.restore(); return; } @@ -878,7 +875,70 @@ if (!empty($currentLocation) && is_array($currentLocation)) { ctx.lineWidth = 2; ctx.strokeStyle = moonStroke; ctx.stroke(); + } + + function drawMoonWithTerminator(ctx, centerX, centerY, radiusPx, terminatorInfo) { + const phaseFraction = terminatorInfo.phaseFraction; + const brightSideAngleRad = terminatorInfo.brightSideAngleRad; + const cosPhase = Math.max(-1, Math.min(1, 2 * phaseFraction - 1)); + const isInverted = STATE.invertMap; + const textureReady = MOON_TEXTURE.complete && MOON_TEXTURE.naturalWidth > 0; + const moonStroke = isInverted ? 'rgba(70, 78, 96, 0.75)' : 'rgba(245,248,255,0.55)'; + + ctx.save(); + ctx.translate(centerX, centerY); + ctx.rotate(brightSideAngleRad); + + if (!textureReady) { + drawMoonWithTerminatorFlat(ctx, radiusPx, phaseFraction, cosPhase, isInverted); + ctx.restore(); + return; + } + + // Dunkle Mondscheibe als Basis (Neumondseite), darĂ¼ber wird die + // Textur nur im beleuchteten Bereich eingeblendet. + ctx.save(); + ctx.beginPath(); + ctx.arc(0, 0, radiusPx, 0, Math.PI * 2); + ctx.clip(); + ctx.fillStyle = isInverted ? 'rgba(210, 214, 224, 0.94)' : 'rgba(8, 10, 16, 0.94)'; + ctx.fill(); + + if (phaseFraction > 0.001) { + ctx.save(); + if (phaseFraction < 0.999) { + ctx.beginPath(); + for (let i = 0; i <= 72; i++) { + const t = -radiusPx + 2 * radiusPx * i / 72; + const xr = Math.sqrt(Math.max(0, radiusPx * radiusPx - t * t)); + const xt = -cosPhase * xr; + i === 0 ? ctx.moveTo(xt, t) : ctx.lineTo(xt, t); + } + for (let i = 72; i >= 0; i--) { + const t = -radiusPx + 2 * radiusPx * i / 72; + const xr = Math.sqrt(Math.max(0, radiusPx * radiusPx - t * t)); + ctx.lineTo(xr, t); + } + ctx.closePath(); + ctx.clip(); + } + ctx.globalAlpha = isInverted ? 0.5 : 0.96; + // Die Textur liegt um 180 Grad gedreht vor (Sueden oben, Ost/West + // vertauscht); hier um die Bildmitte drehen, damit sie zur + // Himmelsdarstellung mit Norden oben passt. + ctx.scale(-1, -1); + ctx.drawImage(MOON_TEXTURE, -radiusPx, -radiusPx, radiusPx * 2, radiusPx * 2); + ctx.globalAlpha = 1; + ctx.restore(); + } ctx.restore(); + ctx.restore(); + + ctx.beginPath(); + ctx.arc(centerX, centerY, radiusPx, 0, Math.PI * 2); + ctx.lineWidth = 1.5; + ctx.strokeStyle = moonStroke; + ctx.stroke(); } function chunkStars(stars, size) {