From 1b5fcf74b563e648ab935c5e717b44cb6f254de1 Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Wed, 7 Oct 2026 07:49:14 +0200 Subject: [PATCH] Keep sun and moon visible on orbit when below horizon, just dimmed --- index.html | 260 ++++++++++++++++++++++++++++------------------------- 1 file changed, 140 insertions(+), 120 deletions(-) diff --git a/index.html b/index.html index 1d1e283..5883d91 100644 --- a/index.html +++ b/index.html @@ -22,8 +22,8 @@ min-width: 220px; } #analog-clock { - width: 180px; - height: 180px; + width: 200px; + height: 200px; margin: 0 auto 10px auto; display: block; } @@ -71,48 +71,61 @@ font-size: 11px; margin-left: 4px; } - .moon-icon-container { - width: 18px; - height: 18px; - position: relative; - }
+ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + @@ -237,15 +250,19 @@ var minuteHand = document.getElementById('minute-hand'); var secondHand = document.getElementById('second-hand'); var hourMarks = document.getElementById('hour-marks'); - var rpgArcBg = document.getElementById('rpg-arc-bg'); + var rpgSunArc = document.getElementById('sun-arc'); + var rpgMoonArc = document.getElementById('moon-arc'); var rpgSun = document.getElementById('rpg-sun'); var rpgSunGlow = document.getElementById('rpg-sun-glow'); var rpgSunCore = document.getElementById('rpg-sun-core'); var rpgMoon = document.getElementById('rpg-moon'); - var sunriseMarker = document.getElementById('sunrise-marker'); - var sunsetMarker = document.getElementById('sunset-marker'); - var moonriseMarker = document.getElementById('moonrise-marker'); - var moonsetMarker = document.getElementById('moonset-marker'); + var sunRiseArrow = document.getElementById('sun-rise-arrow'); + var sunSetArrow = document.getElementById('sun-set-arrow'); + var moonRiseArrow = document.getElementById('moon-rise-arrow'); + var moonSetArrow = document.getElementById('moon-set-arrow'); + + var SUN_ORBIT_RADIUS = 55; + var MOON_ORBIT_RADIUS = 75; // Generate hour marks for (var i = 0; i < 12; i++) { @@ -320,7 +337,30 @@ return 'Abnehm. Sichel'; } - var rpgMoonPhaseGroup = null; + function angleForTime(date) { + var hours = date.getHours() + date.getMinutes() / 60; + return ((hours / 24) * 360 - 90) * Math.PI / 180; + } + + function pointOnCircle(date, radius) { + var angle = angleForTime(date); + return { + x: 100 + Math.cos(angle) * radius, + y: 100 + Math.sin(angle) * radius + }; + } + + function arcBetween(startDate, endDate, radius) { + var sp = pointOnCircle(startDate, radius); + var ep = pointOnCircle(endDate, radius); + var startA = angleForTime(startDate) * 180 / Math.PI; + var endA = angleForTime(endDate) * 180 / Math.PI; + var diff = endA - startA; + if (diff < 0) diff += 360; + // Use shorter arc (largeArc=0) unless the difference exceeds 180 + var largeArc = diff > 180 ? 1 : 0; + return 'M ' + sp.x + ' ' + sp.y + ' A ' + radius + ' ' + radius + ' 0 ' + largeArc + ' 1 ' + ep.x + ' ' + ep.y; + } function renderMoonPhaseIcon(phase) { var icon = document.getElementById('moon-phase-icon'); @@ -352,17 +392,19 @@ function renderRpgMoon(phase) { rpgMoon.innerHTML = ''; - var r = 6; + var r = 9; + // Background var bg = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); bg.setAttribute('cx', '100'); bg.setAttribute('cy', '100'); bg.setAttribute('r', r); bg.setAttribute('fill', '#1c1b1f'); rpgMoon.appendChild(bg); + // Illuminated part if (phase < 0.5) { var lit = document.createElementNS('http://www.w3.org/2000/svg', 'path'); var phaseAngle = phase * 360; var rx = r * Math.abs(Math.cos(phaseAngle * Math.PI / 180)); var sweepFlag = phase < 0.25 ? 0 : 1; - lit.setAttribute('d', 'M 100 94 A 6 6 0 0 1 100 106 A ' + rx + ' 6 0 0 ' + sweepFlag + ' 100 94 Z'); + lit.setAttribute('d', 'M 100 91 A 9 9 0 0 1 100 109 A ' + rx + ' 9 0 0 ' + sweepFlag + ' 100 91 Z'); lit.setAttribute('fill', '#e6dfd1'); rpgMoon.appendChild(lit); } else { @@ -370,7 +412,7 @@ var phaseAngle = (1 - phase) * 360; var rx = r * Math.abs(Math.cos(phaseAngle * Math.PI / 180)); var sweepFlag = phase > 0.75 ? 0 : 1; - lit.setAttribute('d', 'M 100 94 A 6 6 0 0 0 100 106 A ' + rx + ' 6 0 0 ' + sweepFlag + ' 100 94 Z'); + lit.setAttribute('d', 'M 100 91 A 9 9 0 0 0 100 109 A ' + rx + ' 9 0 0 ' + sweepFlag + ' 100 91 Z'); lit.setAttribute('fill', '#e6dfd1'); rpgMoon.appendChild(lit); } @@ -394,88 +436,6 @@ minuteHand.setAttribute('transform', 'rotate(' + minuteAngle + ' 100 100)'); secondHand.setAttribute('transform', 'rotate(' + secondAngle + ' 100 100)'); - var sunTimes = SunCalc.getTimes(now, PASSAU_LAT, PASSAU_LON); - var sunriseNext = getNextEvent(sunTimes.sunrise, now, PASSAU_LAT, PASSAU_LON, 'sunrise'); - var sunsetNext = getNextEvent(sunTimes.sunset, now, PASSAU_LAT, PASSAU_LON, 'sunset'); - - function timeToAngle(date) { - var hours = date.getHours() + date.getMinutes() / 60; - return ((hours / 24) * 360 - 90) * Math.PI / 180; - } - - function timeToPoint(date, r) { - var angle = timeToAngle(date); - return { x: 100 + Math.cos(angle) * r, y: 100 + Math.sin(angle) * r }; - } - - var sunOrbitRadius = 62; - var markerRadius = 48; - - var sr = sunriseNext.date || new Date(now.getFullYear(), now.getMonth(), now.getDate(), 6, 0, 0); - var ss = sunsetNext.date || new Date(now.getFullYear(), now.getMonth(), now.getDate(), 18, 0, 0); - var srPoint = timeToPoint(sr, sunOrbitRadius); - var ssPoint = timeToPoint(ss, sunOrbitRadius); - rpgArcBg.setAttribute('d', 'M ' + srPoint.x + ' ' + srPoint.y + ' A ' + sunOrbitRadius + ' ' + sunOrbitRadius + ' 0 0 1 ' + ssPoint.x + ' ' + ssPoint.y); - - if (now >= sunTimes.sunrise && now <= sunTimes.sunset) { - var sunP = timeToPoint(now, sunOrbitRadius); - rpgSun.setAttribute('cx', sunP.x); - rpgSun.setAttribute('cy', sunP.y); - rpgSun.setAttribute('opacity', '1'); - rpgSunGlow.setAttribute('cx', sunP.x); - rpgSunGlow.setAttribute('cy', sunP.y); - rpgSunGlow.setAttribute('opacity', '0.4'); - rpgSunCore.setAttribute('cx', sunP.x); - rpgSunCore.setAttribute('cy', sunP.y); - rpgSunCore.setAttribute('opacity', '1'); - } else { - var sunP = timeToPoint(now, sunOrbitRadius); - rpgSun.setAttribute('cx', sunP.x); - rpgSun.setAttribute('cy', sunP.y); - rpgSun.setAttribute('opacity', '0.4'); - rpgSunGlow.setAttribute('cx', sunP.x); - rpgSunGlow.setAttribute('cy', sunP.y); - rpgSunGlow.setAttribute('opacity', '0.15'); - rpgSunCore.setAttribute('cx', sunP.x); - rpgSunCore.setAttribute('cy', sunP.y); - rpgSunCore.setAttribute('opacity', '0.4'); - } - - var moonTimes = SunCalc.getMoonTimes(now, PASSAU_LAT, PASSAU_LON); - var moonVisible = false; - if (moonTimes.rise && moonTimes.set) { - if (moonTimes.rise < moonTimes.set) { - moonVisible = (now >= moonTimes.rise && now <= moonTimes.set); - } else { - moonVisible = (now >= moonTimes.rise || now <= moonTimes.set); - } - } - var moonP = timeToPoint(now, sunOrbitRadius); - rpgMoon.setAttribute('cx', moonP.x); - rpgMoon.setAttribute('cy', moonP.y); - rpgMoon.setAttribute('opacity', moonVisible ? '1' : '0.25'); - - var srM = timeToPoint(sr, markerRadius); - sunriseMarker.setAttribute('transform', 'translate(' + srM.x + ', ' + srM.y + ')'); - var ssM = timeToPoint(ss, markerRadius); - sunsetMarker.setAttribute('transform', 'translate(' + ssM.x + ', ' + ssM.y + ')'); - - if (moonTimes.rise) { - var mrM = timeToPoint(moonTimes.rise, markerRadius); - moonriseMarker.setAttribute('transform', 'translate(' + mrM.x + ', ' + mrM.y + ')'); - moonriseMarker.setAttribute('opacity', '1'); - } else { - moonriseMarker.setAttribute('opacity', '0'); - } - - if (moonTimes.set) { - var msM = timeToPoint(moonTimes.set, markerRadius); - moonsetMarker.setAttribute('transform', 'translate(' + msM.x + ', ' + msM.y + ')'); - moonsetMarker.setAttribute('opacity', '1'); - } else { - moonsetMarker.setAttribute('opacity', '0'); - } - // Sun times var sunTimes = SunCalc.getTimes(now, PASSAU_LAT, PASSAU_LON); var sunriseNext = getNextEvent(sunTimes.sunrise, now, PASSAU_LAT, PASSAU_LON, 'sunrise'); @@ -496,6 +456,66 @@ document.getElementById('moonset-value').textContent = formatTimeHM(moonsetNext.date); document.getElementById('moonset-when').textContent = moonsetNext.label ? 'ยท ' + moonsetNext.label : ''; + // Sun arc + if (sunTimes.sunrise && sunTimes.sunset) { + rpgSunArc.setAttribute('d', arcBetween(sunTimes.sunrise, sunTimes.sunset, SUN_ORBIT_RADIUS)); + } + + // Moon arc + if (moonTimes.rise && moonTimes.set) { + rpgMoonArc.setAttribute('d', arcBetween(moonTimes.rise, moonTimes.set, MOON_ORBIT_RADIUS)); + } + + // Sun position + var sunP = pointOnCircle(now, SUN_ORBIT_RADIUS); + rpgSun.setAttribute('cx', sunP.x); + rpgSun.setAttribute('cy', sunP.y); + rpgSunGlow.setAttribute('cx', sunP.x); + rpgSunGlow.setAttribute('cy', sunP.y); + rpgSunCore.setAttribute('cx', sunP.x); + rpgSunCore.setAttribute('cy', sunP.y); + + var isDaytime = now >= sunTimes.sunrise && now <= sunTimes.sunset; + rpgSun.setAttribute('opacity', isDaytime ? '1' : '0.35'); + rpgSunGlow.setAttribute('opacity', isDaytime ? '0.4' : '0.15'); + rpgSunCore.setAttribute('opacity', isDaytime ? '1' : '0.35'); + + // Moon position + var moonP = pointOnCircle(now, MOON_ORBIT_RADIUS); + rpgMoon.setAttribute('transform', 'translate(' + moonP.x + ', ' + moonP.y + ')'); + + var moonVisible = false; + if (moonTimes.rise && moonTimes.set) { + if (moonTimes.rise < moonTimes.set) { + moonVisible = (now >= moonTimes.rise && now <= moonTimes.set); + } else { + moonVisible = (now >= moonTimes.rise || now <= moonTimes.set); + } + } + rpgMoon.setAttribute('opacity', moonVisible ? '1' : '0.35'); + + // Sun rise/set arrows + var srP = pointOnCircle(sunTimes.sunrise, SUN_ORBIT_RADIUS); + sunRiseArrow.setAttribute('transform', 'translate(' + srP.x + ', ' + srP.y + ')'); + var ssP = pointOnCircle(sunTimes.sunset, SUN_ORBIT_RADIUS); + sunSetArrow.setAttribute('transform', 'translate(' + ssP.x + ', ' + ssP.y + ')'); + + // Moon rise/set arrows + if (moonTimes.rise) { + var mrP = pointOnCircle(moonTimes.rise, MOON_ORBIT_RADIUS); + moonRiseArrow.setAttribute('transform', 'translate(' + mrP.x + ', ' + mrP.y + ')'); + moonRiseArrow.setAttribute('opacity', '1'); + } else { + moonRiseArrow.setAttribute('opacity', '0'); + } + if (moonTimes.set) { + var msP = pointOnCircle(moonTimes.set, MOON_ORBIT_RADIUS); + moonSetArrow.setAttribute('transform', 'translate(' + msP.x + ', ' + msP.y + ')'); + moonSetArrow.setAttribute('opacity', '1'); + } else { + moonSetArrow.setAttribute('opacity', '0'); + } + // Moon phase var moonIllum = SunCalc.getMoonIllumination(now); document.getElementById('moon-phase-text').textContent =