Add sunrise/sunset effects and improve sun positioning

- Add sunrise (dawn 5-7 AM) with warm gradient, horizon glow, fading stars
- Add sunset (dusk 18-20) with orange gradient, horizon glow, emerging stars
- Widen sun arc from 5-85% to 3-92% for more dramatic sunset positioning
- Lower horizon position for setting/rising sun (35% to 40%)
- Fix mobile viewport with dvh/vw units for all overlay elements
- Reduce overlay opacity for subtler atmospheric effect
This commit is contained in:
tomt610
2026-01-13 20:26:55 +00:00
parent 0066b61746
commit f38f6850c3
2 changed files with 365 additions and 7 deletions
+139 -7
View File
@@ -237,9 +237,9 @@ function createMist() {
* Returns { left: vw%, top: dvh% }
*/
function calculateSunPosition(hour) {
// Daytime is roughly 6 AM to 8 PM (6-20)
// Daytime is roughly 5 AM to 8 PM (5-20)
// Map hour to position along an arc
// 6 AM = far left, low | 12 PM = center, high | 6 PM = far right, low
// 5 AM = far left, low | 12 PM = center, high | 8 PM = far right, low
if (hour === null) hour = 12; // Default to noon if unknown
@@ -249,14 +249,14 @@ function calculateSunPosition(hour) {
// Normalize to 0-1 range (5 AM = 0, 20 PM = 1)
const progress = (clampedHour - 5) / 15;
// Horizontal position: 5% to 85% (left to right)
const left = 5 + progress * 80;
// Horizontal position: 3% to 92% (left to right, wider range)
const left = 3 + progress * 89;
// Vertical position: parabolic arc (high at noon, low at dawn/dusk)
// At progress 0.5 (noon), top should be ~8% (high)
// At progress 0 or 1, top should be ~35% (low, near horizon)
// At progress 0 or 1, top should be ~40% (low, near horizon)
const normalizedProgress = (progress - 0.5) * 2; // -1 to 1
const top = 8 + 27 * (normalizedProgress * normalizedProgress);
const top = 8 + 32 * (normalizedProgress * normalizedProgress);
return { left, top };
}
@@ -327,6 +327,134 @@ function createSunshine(hour) {
return container;
}
/**
* Create sunrise effect (dawn - warm orange/pink sky gradient with low sun)
*/
function createSunrise(hour) {
const container = document.createElement('div');
container.className = 'rpg-weather-particles rpg-sunrise-weather';
// Create sunrise gradient overlay
const sunriseOverlay = document.createElement('div');
sunriseOverlay.className = 'rpg-weather-particle rpg-sunrise-overlay';
container.appendChild(sunriseOverlay);
// Calculate sun position (rising from left horizon)
const sunPos = calculateSunPosition(hour);
// Create the rising sun
const sun = document.createElement('div');
sun.className = 'rpg-weather-particle rpg-clear-sun rpg-sunrise-sun';
sun.style.left = `${sunPos.left}vw`;
sun.style.top = `${sunPos.top}dvh`;
container.appendChild(sun);
// Create sun glow (more orange during sunrise)
const sunGlow = document.createElement('div');
sunGlow.className = 'rpg-weather-particle rpg-clear-sun-glow rpg-sunrise-glow';
sunGlow.style.left = `${sunPos.left}vw`;
sunGlow.style.top = `${sunPos.top}dvh`;
container.appendChild(sunGlow);
// Create horizon glow
const horizonGlow = document.createElement('div');
horizonGlow.className = 'rpg-weather-particle rpg-sunrise-horizon-glow';
container.appendChild(horizonGlow);
// Add some fading stars (still visible at dawn)
for (let i = 0; i < 15; i++) {
const star = document.createElement('div');
star.className = 'rpg-weather-particle rpg-night-star rpg-sunrise-fading-star';
star.style.left = `${Math.random() * 100}vw`;
star.style.top = `${Math.random() * 40}dvh`;
star.style.animationDelay = `${Math.random() * 3}s`;
const size = 1 + Math.random() * 1.5;
star.style.width = `${size}px`;
star.style.height = `${size}px`;
container.appendChild(star);
}
// Add some golden dust motes
for (let i = 0; i < 12; i++) {
const particle = document.createElement('div');
particle.className = 'rpg-weather-particle rpg-clear-dust-mote';
particle.style.left = `${Math.random() * 100}vw`;
particle.style.top = `${Math.random() * 100}dvh`;
particle.style.animationDelay = `${Math.random() * 15}s`;
particle.style.animationDuration = `${12 + Math.random() * 8}s`;
const size = 2 + Math.random() * 3;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
container.appendChild(particle);
}
return container;
}
/**
* Create sunset effect (dusk - warm red/purple sky gradient with low sun)
*/
function createSunset(hour) {
const container = document.createElement('div');
container.className = 'rpg-weather-particles rpg-sunset-weather';
// Create sunset gradient overlay
const sunsetOverlay = document.createElement('div');
sunsetOverlay.className = 'rpg-weather-particle rpg-sunset-overlay';
container.appendChild(sunsetOverlay);
// Calculate sun position (setting on right horizon)
const sunPos = calculateSunPosition(hour);
// Create the setting sun
const sun = document.createElement('div');
sun.className = 'rpg-weather-particle rpg-clear-sun rpg-sunset-sun';
sun.style.left = `${sunPos.left}vw`;
sun.style.top = `${sunPos.top}dvh`;
container.appendChild(sun);
// Create sun glow (more red during sunset)
const sunGlow = document.createElement('div');
sunGlow.className = 'rpg-weather-particle rpg-clear-sun-glow rpg-sunset-glow';
sunGlow.style.left = `${sunPos.left}vw`;
sunGlow.style.top = `${sunPos.top}dvh`;
container.appendChild(sunGlow);
// Create horizon glow
const horizonGlow = document.createElement('div');
horizonGlow.className = 'rpg-weather-particle rpg-sunset-horizon-glow';
container.appendChild(horizonGlow);
// Add some early stars (appearing at dusk)
for (let i = 0; i < 20; i++) {
const star = document.createElement('div');
star.className = 'rpg-weather-particle rpg-night-star rpg-sunset-emerging-star';
star.style.left = `${Math.random() * 100}vw`;
star.style.top = `${Math.random() * 50}dvh`;
star.style.animationDelay = `${Math.random() * 5}s`;
const size = 1 + Math.random() * 1.5;
star.style.width = `${size}px`;
star.style.height = `${size}px`;
container.appendChild(star);
}
// Add some golden/pink dust motes
for (let i = 0; i < 12; i++) {
const particle = document.createElement('div');
particle.className = 'rpg-weather-particle rpg-clear-dust-mote rpg-sunset-dust';
particle.style.left = `${Math.random() * 100}vw`;
particle.style.top = `${Math.random() * 100}dvh`;
particle.style.animationDelay = `${Math.random() * 15}s`;
particle.style.animationDuration = `${12 + Math.random() * 8}s`;
const size = 2 + Math.random() * 3;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
container.appendChild(particle);
}
return container;
}
/**
* Create clear nighttime weather effect with moon, stars, and fireflies
*/
@@ -572,9 +700,13 @@ export function updateWeatherEffect() {
weatherContainer = createMist();
break;
case 'sunny':
// Use nighttime effect for clear weather at night
// Use appropriate effect based on time of day
if (timeOfDay === 'night') {
weatherContainer = createNighttime(hour);
} else if (timeOfDay === 'dawn') {
weatherContainer = createSunrise(hour);
} else if (timeOfDay === 'dusk') {
weatherContainer = createSunset(hour);
} else {
weatherContainer = createSunshine(hour);
}
+226
View File
@@ -9806,6 +9806,200 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play {
}
}
/* ===== Sunrise Effects (Dawn) ===== */
.rpg-sunrise-weather {
overflow: hidden;
}
/* Sunrise sky gradient overlay */
.rpg-sunrise-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100dvh;
background: linear-gradient(to bottom,
rgba(40, 30, 80, 0.1) 0%,
rgba(120, 60, 120, 0.08) 15%,
rgba(200, 100, 100, 0.1) 35%,
rgba(255, 140, 100, 0.12) 55%,
rgba(255, 180, 120, 0.1) 75%,
rgba(255, 200, 150, 0.08) 100%);
animation: rpg-sunrise-sky-transition 30s ease-in-out infinite alternate;
pointer-events: none;
}
@keyframes rpg-sunrise-sky-transition {
0% {
opacity: 0.8;
}
100% {
opacity: 1;
}
}
/* Sunrise sun - more orange/red */
.rpg-sunrise-sun {
background: radial-gradient(circle at 40% 40%,
rgba(255, 255, 220, 1) 0%,
rgba(255, 220, 150, 1) 30%,
rgba(255, 160, 80, 0.9) 60%,
rgba(255, 100, 50, 0.6) 80%,
rgba(255, 80, 30, 0) 100%) !important;
box-shadow:
0 0 40px 15px rgba(255, 180, 100, 0.6),
0 0 80px 30px rgba(255, 140, 80, 0.4),
0 0 120px 50px rgba(255, 100, 50, 0.2) !important;
}
/* Sunrise sun glow - warm orange */
.rpg-sunrise-glow {
background: radial-gradient(circle at center,
rgba(255, 200, 150, 0.35) 0%,
rgba(255, 160, 100, 0.2) 30%,
rgba(255, 120, 80, 0.1) 50%,
transparent 70%) !important;
}
/* Horizon glow for sunrise */
.rpg-sunrise-horizon-glow {
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
height: 40dvh;
background: linear-gradient(to top,
rgba(255, 160, 100, 0.15) 0%,
rgba(255, 140, 90, 0.1) 20%,
rgba(255, 120, 80, 0.05) 50%,
rgba(255, 100, 70, 0.02) 75%,
transparent 100%);
animation: rpg-horizon-glow-pulse 8s ease-in-out infinite;
pointer-events: none;
}
@keyframes rpg-horizon-glow-pulse {
0%, 100% {
opacity: 0.7;
}
50% {
opacity: 1;
}
}
/* Fading stars at sunrise */
.rpg-sunrise-fading-star {
opacity: 0.3 !important;
animation: rpg-star-fade-out 4s ease-in-out infinite !important;
}
@keyframes rpg-star-fade-out {
0%, 100% {
opacity: 0.2;
}
50% {
opacity: 0.4;
}
}
/* ===== Sunset Effects (Dusk) ===== */
.rpg-sunset-weather {
overflow: hidden;
}
/* Sunset sky gradient overlay */
.rpg-sunset-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100dvh;
background: linear-gradient(to bottom,
rgba(30, 20, 60, 0.12) 0%,
rgba(80, 40, 100, 0.1) 15%,
rgba(150, 60, 90, 0.12) 30%,
rgba(220, 80, 70, 0.12) 50%,
rgba(255, 120, 80, 0.12) 70%,
rgba(255, 160, 100, 0.1) 85%,
rgba(255, 180, 120, 0.06) 100%);
animation: rpg-sunset-sky-transition 30s ease-in-out infinite alternate;
pointer-events: none;
}
@keyframes rpg-sunset-sky-transition {
0% {
opacity: 1;
}
100% {
opacity: 0.8;
}
}
/* Sunset sun - more red/deep orange */
.rpg-sunset-sun {
background: radial-gradient(circle at 40% 40%,
rgba(255, 240, 200, 1) 0%,
rgba(255, 180, 100, 1) 30%,
rgba(255, 120, 60, 0.9) 60%,
rgba(255, 80, 40, 0.6) 80%,
rgba(200, 50, 30, 0) 100%) !important;
box-shadow:
0 0 40px 15px rgba(255, 140, 80, 0.6),
0 0 80px 30px rgba(255, 100, 60, 0.4),
0 0 120px 50px rgba(200, 60, 40, 0.2) !important;
}
/* Sunset sun glow - deep orange/red */
.rpg-sunset-glow {
background: radial-gradient(circle at center,
rgba(255, 160, 120, 0.35) 0%,
rgba(255, 120, 80, 0.2) 30%,
rgba(200, 80, 60, 0.1) 50%,
transparent 70%) !important;
}
/* Horizon glow for sunset */
.rpg-sunset-horizon-glow {
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
height: 45dvh;
background: linear-gradient(to top,
rgba(255, 120, 60, 0.18) 0%,
rgba(255, 100, 50, 0.12) 20%,
rgba(220, 70, 50, 0.06) 45%,
rgba(150, 50, 60, 0.02) 70%,
transparent 100%);
animation: rpg-horizon-glow-pulse 8s ease-in-out infinite;
pointer-events: none;
}
/* Emerging stars at sunset */
.rpg-sunset-emerging-star {
animation: rpg-star-emerge 5s ease-in-out infinite !important;
}
@keyframes rpg-star-emerge {
0%, 100% {
opacity: 0.3;
}
50% {
opacity: 0.7;
}
}
/* Sunset dust motes - pinkish tint */
.rpg-sunset-dust {
background: radial-gradient(circle at 30% 30%,
rgba(255, 200, 180, 0.9) 0%,
rgba(255, 180, 160, 0.6) 50%,
rgba(255, 160, 140, 0) 100%) !important;
box-shadow: 0 0 6px 2px rgba(255, 180, 160, 0.4) !important;
}
/* Lens flare effect */
.rpg-clear-lens-flare {
position: fixed;
@@ -10180,6 +10374,12 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play {
.rpg-night-shooting-star {
animation-duration: 18s;
}
/* Sunrise/Sunset mobile optimizations */
.rpg-sunrise-horizon-glow,
.rpg-sunset-horizon-glow {
height: 35%;
}
}
/* Foreground mode - reduced opacity for celestial bodies to not obstruct content */
@@ -10227,6 +10427,32 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play {
opacity: 0.6;
}
/* Sunrise/Sunset foreground mode */
.rpg-weather-foreground .rpg-sunrise-overlay,
.rpg-weather-foreground .rpg-sunset-overlay {
opacity: 0.4;
}
.rpg-weather-foreground .rpg-sunrise-horizon-glow,
.rpg-weather-foreground .rpg-sunset-horizon-glow {
opacity: 0.3;
}
.rpg-weather-foreground .rpg-sunrise-sun,
.rpg-weather-foreground .rpg-sunset-sun {
opacity: 0.5 !important;
}
.rpg-weather-foreground .rpg-sunrise-glow,
.rpg-weather-foreground .rpg-sunset-glow {
opacity: 0.3 !important;
}
.rpg-weather-foreground .rpg-sunrise-fading-star,
.rpg-weather-foreground .rpg-sunset-emerging-star {
opacity: 0.2 !important;
}
/* Lightning flash effect */
.rpg-lightning {
position: fixed;