diff --git a/src/components/content/heroes/aurora/weather-easter-egg/daylight-percentage-calculator.ts b/src/components/content/heroes/aurora/weather-easter-egg/daylight-percentage-calculator.ts new file mode 100644 index 000000000..615e0f403 --- /dev/null +++ b/src/components/content/heroes/aurora/weather-easter-egg/daylight-percentage-calculator.ts @@ -0,0 +1,42 @@ +export const getSunlightPercentage = ( + sunriseTime: number, + sunsetTime: number, + time: number, +) => { + const totalDaylightMinutes = sunsetTime - sunriseTime; + if (totalDaylightMinutes <= 0) { + return 20; + } + const currentMinutes = time - sunriseTime; + const sunlightPercentage = (currentMinutes / totalDaylightMinutes) * 100; + + if (sunlightPercentage < 0) { + return 0; + } + if (sunlightPercentage > 100) { + return 100; + } + return Math.round(sunlightPercentage); +}; + +export const getNighttimePercentage = ( + sunriseTime: number, + sunsetTime: number, + time: number, +) => { + const totalDaylightMinutes = sunsetTime - sunriseTime; + const totalNighttimeMinutes = 86400000 - totalDaylightMinutes; + if (totalNighttimeMinutes <= 0) { + return 0; + } + const currentMinutes = time - sunsetTime; + const nighttimePercentage = (currentMinutes / totalNighttimeMinutes) * 100; + + if (nighttimePercentage < 0) { + return 0; + } + if (nighttimePercentage > 100) { + return 100; + } + return Math.round(nighttimePercentage); +}; diff --git a/src/components/content/heroes/aurora/weather-easter-egg/moon.tsx b/src/components/content/heroes/aurora/weather-easter-egg/moon.tsx new file mode 100644 index 000000000..7b3b97fb0 --- /dev/null +++ b/src/components/content/heroes/aurora/weather-easter-egg/moon.tsx @@ -0,0 +1,97 @@ +import styled from 'styled-components'; +import React, { useEffect, useState } from 'react'; + +interface MoonProps { + nightPercentage: number; +} + +const generateStars = (starCount: number) => { + const stars: React.JSX.Element[] = []; + + for (let i = 0; i < starCount; i++) { + stars.push( + , + ); + } + + return stars; +}; + +const BackgroundDiv = styled.div<{ nightPercentage: number }>` + position: absolute; + background: #000000; + width: 100%; + height: 100%; + opacity: ${(props) => + props.nightPercentage === 0 || props.nightPercentage === 100 ? '0' : '1'}; +`; + +const StarsDiv = styled.div<{ x: number; y: number }>` + position: absolute; + width: 3px; + height: 3px; + top: ${(props) => props.y}%; + left: ${(props) => props.x}%; + border-radius: 100%; + background: #ffffff; +`; + +const MoonDiv = styled.div<{ nightPercentage: number }>` + position: absolute; + width: 100px; + height: 100px; + opacity: ${(props) => + props.nightPercentage === 0 || props.nightPercentage === 100 ? '0' : '1'}; + background: #ffffff; + left: calc(${(props) => props.nightPercentage}% - 50px); + bottom: calc( + ${(props) => + (1 / 125) * + (-(props.nightPercentage - 50) * (props.nightPercentage - 50)) + + 70}% + // parabola formula to get the moon to move in a parabola + ); + border-radius: 50%; + filter: blur(5px); +`; + +const ParallaxDiv = styled.div<{ x: number; y: number }>` + position: absolute; + width: 100%; + height: 100%; + transform: translate( + ${(props) => -props.x * 0.09}px, + ${(props) => -props.y * 0.09}px + ); +`; + +export const Moon = ({ nightPercentage }: MoonProps) => { + const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); + const [stars, setStars] = useState([]); + + useEffect(() => { + const handleMouseMove = (event) => { + setMousePos({ x: event.clientX, y: event.clientY }); + }; + + window.addEventListener('mousemove', handleMouseMove); + + return () => { + window.removeEventListener('mousemove', handleMouseMove); + }; + }, []); + + useEffect(() => { + setStars(generateStars(120)); + }, []); + + return ( + <> + + + {nightPercentage === 0 || nightPercentage === 100 ? '' : stars} + + + + ); +}; diff --git a/src/components/content/heroes/aurora/weather-easter-egg/sun-percentage-calculator.ts b/src/components/content/heroes/aurora/weather-easter-egg/sun-percentage-calculator.ts deleted file mode 100644 index 0924043f9..000000000 --- a/src/components/content/heroes/aurora/weather-easter-egg/sun-percentage-calculator.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const getSunlightPercentage = ( - sunriseTime: number, - sunsetTime: number, - time: number, -) => { - const totalDaylightMinutes = (sunsetTime - sunriseTime) / (1000 * 60); - if (totalDaylightMinutes <= 0) { - return 20; - } - const currentMinutes = (time - sunriseTime) / (1000 * 60); - const sunlightPercentage = (currentMinutes / totalDaylightMinutes) * 100; - - if (sunlightPercentage < 0) { - return 0; - } - if (sunlightPercentage > 100) { - return 100; - } - return Math.round(sunlightPercentage); -}; diff --git a/src/components/content/heroes/aurora/weather-easter-egg/sun.test.ts b/src/components/content/heroes/aurora/weather-easter-egg/sun.test.ts index 46670926d..49893566e 100644 --- a/src/components/content/heroes/aurora/weather-easter-egg/sun.test.ts +++ b/src/components/content/heroes/aurora/weather-easter-egg/sun.test.ts @@ -1,4 +1,4 @@ -import { getSunlightPercentage } from './sun-percentage-calculator'; +import { getSunlightPercentage } from './daylight-percentage-calculator'; describe('getSunlightPercentage', () => { const sunriseTime = new Date('2023-07-14T06:00:00Z').getTime(); diff --git a/src/components/content/heroes/aurora/weather-easter-egg/sun.tsx b/src/components/content/heroes/aurora/weather-easter-egg/sun.tsx index 283bb4558..cdc896a3b 100644 --- a/src/components/content/heroes/aurora/weather-easter-egg/sun.tsx +++ b/src/components/content/heroes/aurora/weather-easter-egg/sun.tsx @@ -5,9 +5,13 @@ import styled, { keyframes } from 'styled-components'; import { useEffect, useState } from 'react'; import React from 'react'; import { getSunTime } from './weather-api'; -import { getSunlightPercentage } from './sun-percentage-calculator'; +import { + getNighttimePercentage, + getSunlightPercentage, +} from './daylight-percentage-calculator'; import { Flare, FlareType } from '../flare'; import { DefaultFlares } from '../default-flares'; +import { Moon } from './moon'; const getSunYPosition = (timePercent: number) => { return (1 / 125) * (-(timePercent - 50) * (timePercent - 50)) + 60; // parabola formula to get the sun to move in a parabola @@ -24,6 +28,11 @@ const getSunReflectionYPosition = (timePercent: number) => { ); }; +interface bgProps { + time: number; + sunrise: number; + sunset: number; +} const rotatingAnimation = keyframes` 0% { transform: rotate(0deg); @@ -33,6 +42,79 @@ const rotatingAnimation = keyframes` } `; +const sunBackgroundAnimation = keyframes` + 0% { + width: 500%; + height: 500%; + transform: translate(-25%, -25%); + } + 7% { + width: 0; + height: 0; + } + 93% { + width: 0; + height: 0; + } + 100% { + width: 500%; + height: 500%; + transform: translate(-25%, -25%); + } + `; + +const backgroundAnimation = keyframes` + 0% { + opacity: .7; + } + 7% { + opacity: 0; + } + 93% { + opacity: 0; + } + 100% { + opacity: .7; + } +`; + +const SunBackgroundDiv = styled.div` + position: relative; + background: radial-gradient( + circle at 50% 50%, + #ff6a00c4 0%, + #ff6a00c4 50%, + #ffffff00 100% + ); + + animation: ${sunBackgroundAnimation} + ${(props) => (props.sunset - props.sunrise) / 1000}s linear infinite; + animation-delay: ${(props) => + `-${((props.time / 100) * (props.sunset - props.sunrise)) / 1000}s`}; + z-index: -1; + opacity: 0.7; + border-radius: 500%; + filter: blur(200px); +`; + +const BackgroundDiv = styled.div` + position: absolute; + width: 100%; + height: 120%; + top: 0; + left: 0; + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0) 0%, + rgb(255, 38, 38) 100% + ); + z-index: -2; + animation: ${backgroundAnimation} + ${(props) => (props.sunset - props.sunrise) / 1000}s linear infinite; + animation-delay: ${(props) => + `-${((props.time / 100) * (props.sunset - props.sunrise)) / 1000}s`}; +`; + // Sunshine effect around the sun const AuroraSunShineDiv = styled.div` background-image: url(${SUNSHINE}); @@ -87,6 +169,7 @@ const AuroraSunReflectionDiv = styled.div<{ timePercent: number }>` export const Sun = () => { const [timePercent, setTimePercent] = useState(0); + const [nightTimePercent, setNightTimePercent] = useState(0); const [sunrise, setSunrise] = useState(0); const [sunset, setSunset] = useState(0); @@ -96,14 +179,22 @@ export const Sun = () => { setSunrise(sunriseTime); setSunset(sunsetTime); setTimePercent( - getSunlightPercentage(sunriseTime, sunsetTime, +new Date()), + getSunlightPercentage(sunriseTime, sunsetTime, +new Date() + 86400000), + ); + setNightTimePercent( + getNighttimePercentage(sunriseTime, sunsetTime, +new Date() + 86400000), ); }; fetchData(); const interval = setInterval(() => { - setTimePercent(getSunlightPercentage(sunrise, sunset, +new Date())); + setTimePercent( + getSunlightPercentage(sunrise, sunset, +new Date() + 86400000), + ); + setNightTimePercent( + getNighttimePercentage(sunrise, sunset, +new Date() + 86400000), + ); }, 10000); return () => { @@ -113,10 +204,17 @@ export const Sun = () => { return ( <> + + +