Remove sun element, add RPG sun/moon arc inside analog clock with phase rendering
This commit is contained in:
1 parent
7b89afe36b
commit
18c063c623
1 file changed
+156
-36
+156
-36
@@ -8,20 +8,6 @@
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; overflow: hidden; width: 100%; height: 100%; font-family: monospace; }
|
||||
#vanta { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; }
|
||||
#sun {
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
right: 80px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 35%, #f3ede1, #e0914f);
|
||||
box-shadow: 0 0 60px rgba(224, 145, 79, 0.6);
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
}
|
||||
#info-panel {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
@@ -36,8 +22,8 @@
|
||||
min-width: 220px;
|
||||
}
|
||||
#analog-clock {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
margin: 0 auto 10px auto;
|
||||
display: block;
|
||||
}
|
||||
@@ -94,15 +80,39 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="vanta"></div>
|
||||
<div id="sun"></div>
|
||||
<div id="info-panel">
|
||||
<svg id="analog-clock" viewBox="0 0 140 140">
|
||||
<circle cx="70" cy="70" r="65" fill="rgba(28,27,31,0.3)" stroke="#e6dfd1" stroke-width="2"/>
|
||||
<svg id="analog-clock" viewBox="0 0 200 200">
|
||||
<circle cx="100" cy="100" r="95" fill="rgba(28,27,31,0.3)" stroke="#e6dfd1" stroke-width="2"/>
|
||||
|
||||
<!-- RPG day/night arc background -->
|
||||
<path id="rpg-arc-bg" d="" fill="none" stroke="#3a383d" stroke-width="3" opacity="0.6"/>
|
||||
|
||||
<!-- RPG sun position dot -->
|
||||
<circle id="rpg-sun" cx="100" cy="100" r="5" fill="#e0914f"/>
|
||||
|
||||
<!-- RPG moon position dot -->
|
||||
<circle id="rpg-moon" cx="100" cy="100" r="5" fill="#b0a89a"/>
|
||||
|
||||
<!-- Hour marks -->
|
||||
<g id="hour-marks"></g>
|
||||
<line id="hour-hand" x1="70" y1="70" x2="70" y2="25" stroke="#e6dfd1" stroke-width="4" stroke-linecap="round"/>
|
||||
<line id="minute-hand" x1="70" y1="70" x2="70" y2="15" stroke="#e6dfd1" stroke-width="3" stroke-linecap="round"/>
|
||||
<line id="second-hand" x1="70" y1="70" x2="70" y2="10" stroke="#e0914f" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<circle cx="70" cy="70" r="4" fill="#e0914f"/>
|
||||
|
||||
<!-- Sunrise/sunset markers (outside clock) -->
|
||||
<g id="sun-marker" fill="#e0914f">
|
||||
<circle id="sunrise-marker" cx="100" cy="100" r="3"/>
|
||||
<circle id="sunset-marker" cx="100" cy="100" r="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Moonrise/moonset markers (outside clock) -->
|
||||
<g id="moon-marker" fill="#b0a89a">
|
||||
<circle id="moonrise-marker" cx="100" cy="100" r="3"/>
|
||||
<circle id="moonset-marker" cx="100" cy="100" r="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Clock hands -->
|
||||
<line id="hour-hand" x1="100" y1="100" x2="100" y2="35" stroke="#e6dfd1" stroke-width="4" stroke-linecap="round"/>
|
||||
<line id="minute-hand" x1="100" y1="100" x2="100" y2="20" stroke="#e6dfd1" stroke-width="3" stroke-linecap="round"/>
|
||||
<line id="second-hand" x1="100" y1="100" x2="100" y2="14" stroke="#e0914f" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<circle cx="100" cy="100" r="4" fill="#e0914f"/>
|
||||
</svg>
|
||||
<div id="digital-clock">00:00:00</div>
|
||||
<div class="info-row">
|
||||
@@ -225,14 +235,28 @@
|
||||
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 rpgSun = document.getElementById('rpg-sun');
|
||||
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 rpgArcBg = document.getElementById('rpg-arc-bg');
|
||||
var rpgSun = document.getElementById('rpg-sun');
|
||||
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');
|
||||
|
||||
// Generate hour marks
|
||||
for (var i = 0; i < 12; i++) {
|
||||
var angle = (i * 30) * Math.PI / 180;
|
||||
var x1 = 70 + Math.sin(angle) * 58;
|
||||
var y1 = 70 - Math.cos(angle) * 58;
|
||||
var x2 = 70 + Math.sin(angle) * 62;
|
||||
var y2 = 70 - Math.cos(angle) * 62;
|
||||
var x1 = 100 + Math.sin(angle) * 85;
|
||||
var y1 = 100 - Math.cos(angle) * 85;
|
||||
var x2 = 100 + Math.sin(angle) * 90;
|
||||
var y2 = 100 - Math.cos(angle) * 90;
|
||||
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', x1);
|
||||
line.setAttribute('y1', y1);
|
||||
@@ -299,17 +323,16 @@
|
||||
return 'Abnehm. Sichel';
|
||||
}
|
||||
|
||||
var rpgMoonPhaseGroup = null;
|
||||
|
||||
function renderMoonPhaseIcon(phase) {
|
||||
var icon = document.getElementById('moon-phase-icon');
|
||||
icon.innerHTML = '';
|
||||
// Background dark circle
|
||||
var bg = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
|
||||
bg.setAttribute('cx', '12'); bg.setAttribute('cy', '12'); bg.setAttribute('r', '9');
|
||||
bg.setAttribute('fill', '#1c1b1f');
|
||||
icon.appendChild(bg);
|
||||
// The illuminated part
|
||||
if (phase < 0.5) {
|
||||
// Waxing - light on right
|
||||
var lit = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
var r = 9;
|
||||
var phaseAngle = phase * 360;
|
||||
@@ -319,7 +342,6 @@
|
||||
lit.setAttribute('fill', '#e6dfd1');
|
||||
icon.appendChild(lit);
|
||||
} else {
|
||||
// Waning - light on left
|
||||
var lit = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
var r = 9;
|
||||
var phaseAngle = (1 - phase) * 360;
|
||||
@@ -331,6 +353,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
function renderRpgMoon(phase) {
|
||||
rpgMoon.innerHTML = '';
|
||||
var r = 6;
|
||||
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);
|
||||
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('fill', '#e6dfd1');
|
||||
rpgMoon.appendChild(lit);
|
||||
} else {
|
||||
var lit = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
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('fill', '#e6dfd1');
|
||||
rpgMoon.appendChild(lit);
|
||||
}
|
||||
}
|
||||
|
||||
function updateClockAndEvents() {
|
||||
var now = new Date();
|
||||
|
||||
@@ -345,9 +393,82 @@
|
||||
var minuteAngle = (m + s / 60) * 6;
|
||||
var secondAngle = s * 6;
|
||||
|
||||
hourHand.setAttribute('transform', 'rotate(' + hourAngle + ' 70 70)');
|
||||
minuteHand.setAttribute('transform', 'rotate(' + minuteAngle + ' 70 70)');
|
||||
secondHand.setAttribute('transform', 'rotate(' + secondAngle + ' 70 70)');
|
||||
hourHand.setAttribute('transform', 'rotate(' + hourAngle + ' 100 100)');
|
||||
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 sunRadius = 55;
|
||||
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, sunRadius);
|
||||
var ssPoint = timeToPoint(ss, sunRadius);
|
||||
rpgArcBg.setAttribute('d', 'M ' + srPoint.x + ' ' + srPoint.y + ' A ' + sunRadius + ' ' + sunRadius + ' 0 0 1 ' + ssPoint.x + ' ' + ssPoint.y);
|
||||
|
||||
if (now >= sunTimes.sunrise && now <= sunTimes.sunset) {
|
||||
var sunP = timeToPoint(now, sunRadius);
|
||||
rpgSun.setAttribute('cx', sunP.x);
|
||||
rpgSun.setAttribute('cy', sunP.y);
|
||||
rpgSun.setAttribute('opacity', '1');
|
||||
} else {
|
||||
var sunP = timeToPoint(now, sunRadius);
|
||||
rpgSun.setAttribute('cx', sunP.x);
|
||||
rpgSun.setAttribute('cy', sunP.y);
|
||||
rpgSun.setAttribute('opacity', '0.25');
|
||||
}
|
||||
|
||||
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, sunRadius);
|
||||
rpgMoon.setAttribute('cx', moonP.x);
|
||||
rpgMoon.setAttribute('cy', moonP.y);
|
||||
rpgMoon.setAttribute('opacity', moonVisible ? '1' : '0.25');
|
||||
|
||||
var outerRadius = 98;
|
||||
var srM = timeToPoint(sr, outerRadius);
|
||||
sunriseMarker.setAttribute('cx', srM.x);
|
||||
sunriseMarker.setAttribute('cy', srM.y);
|
||||
var ssM = timeToPoint(ss, outerRadius);
|
||||
sunsetMarker.setAttribute('cx', ssM.x);
|
||||
sunsetMarker.setAttribute('cy', ssM.y);
|
||||
|
||||
if (moonTimes.rise) {
|
||||
var mrM = timeToPoint(moonTimes.rise, outerRadius);
|
||||
moonriseMarker.setAttribute('cx', mrM.x);
|
||||
moonriseMarker.setAttribute('cy', mrM.y);
|
||||
moonriseMarker.setAttribute('opacity', '1');
|
||||
} else {
|
||||
moonriseMarker.setAttribute('opacity', '0');
|
||||
}
|
||||
|
||||
if (moonTimes.set) {
|
||||
var msM = timeToPoint(moonTimes.set, outerRadius);
|
||||
moonsetMarker.setAttribute('cx', msM.x);
|
||||
moonsetMarker.setAttribute('cy', msM.y);
|
||||
moonsetMarker.setAttribute('opacity', '1');
|
||||
} else {
|
||||
moonsetMarker.setAttribute('opacity', '0');
|
||||
}
|
||||
|
||||
// Sun times
|
||||
var sunTimes = SunCalc.getTimes(now, PASSAU_LAT, PASSAU_LON);
|
||||
@@ -374,10 +495,10 @@
|
||||
document.getElementById('moon-phase-text').textContent =
|
||||
getMoonPhaseText(moonIllum.phase) + ' ' + Math.round(moonIllum.fraction * 100) + '%';
|
||||
renderMoonPhaseIcon(moonIllum.phase);
|
||||
renderRpgMoon(moonIllum.phase);
|
||||
}
|
||||
|
||||
var startTime = Date.now();
|
||||
var sunEl = document.getElementById('sun');
|
||||
|
||||
function animate() {
|
||||
var elapsed = (Date.now() - startTime) % CYCLE;
|
||||
@@ -393,7 +514,6 @@
|
||||
backgroundColor: c.bg
|
||||
});
|
||||
document.body.style.backgroundColor = '#' + ('00000' + c.bg.toString(16)).slice(-6);
|
||||
sunEl.style.opacity = c.sunVis;
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user