diff --git a/public/css/index.css b/public/css/index.css index b534acb..1e13dd4 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -1,3 +1,47 @@ +.raindrop { + position: absolute; + background-color: white; + border-radius: 50%; + pointer-events: none; + z-index: 1; +} + +.star, +.snowflake { + position: absolute; + background-color: white; + border-radius: 50%; + pointer-events: none; + z-index: 1; +} + +.star { + animation: twinkle ease-in-out infinite alternate; +} + +.shooting-star { + position: absolute; + background: linear-gradient(90deg, white, transparent); + width: 100px; + height: 2px; + opacity: 0.8; + border-radius: 2px; + transform-origin: left center; +} + + +@keyframes twinkle { + from { + opacity: 0.3; + transform: scale(1); + } + to { + opacity: 1; + transform: scale(1.2); + } +} + +/* actual styles below */ body { font-family: system-ui, sans-serif; background-color: var(--background); @@ -9,22 +53,6 @@ body { align-items: center; } -.snowflake { - position: absolute; - background-color: white; - border-radius: 50%; - pointer-events: none; - z-index: 1; -} - -.raindrop { - position: absolute; - background-color: white; - border-radius: 50%; - pointer-events: none; - z-index: 1; -} - .hidden { display: none !important; } @@ -38,7 +66,7 @@ body { flex-direction: column; align-items: center; margin-bottom: 2rem; - max-width: 600px; + max-width: 700px; width: 100%; } @@ -65,6 +93,7 @@ body { .badges { max-width: 700px; + box-sizing: border-box; display: flex; flex-direction: row; justify-content: center; @@ -226,7 +255,7 @@ ul { list-style: none; padding: 0; width: 100%; - max-width: 600px; + max-width: 700px; } .activities { @@ -234,7 +263,8 @@ ul { flex-direction: column; gap: 1rem; width: 100%; - max-width: 600px; + max-width: 700px; + box-sizing: border-box; padding: 0; margin: 0; } diff --git a/public/js/stars.js b/public/js/stars.js new file mode 100644 index 0000000..650544e --- /dev/null +++ b/public/js/stars.js @@ -0,0 +1,67 @@ +document.addEventListener("DOMContentLoaded", () => { + const container = document.createElement("div"); + container.style.position = "fixed"; + container.style.top = "0"; + container.style.left = "0"; + container.style.width = "100vw"; + container.style.height = "100vh"; + container.style.pointerEvents = "none"; + container.style.overflow = "hidden"; + container.style.zIndex = "9999"; + document.body.appendChild(container); + + for (let i = 0; i < 60; i++) { + const star = document.createElement("div"); + const size = Math.random() * 2 + 1; + star.style.position = "absolute"; + star.style.width = `${size}px`; + star.style.height = `${size}px`; + star.style.background = "white"; + star.style.borderRadius = "50%"; + star.style.opacity = Math.random(); + star.style.top = `${Math.random() * 100}vh`; + star.style.left = `${Math.random() * 100}vw`; + star.style.animation = `twinkle ${Math.random() * 3 + 2}s infinite alternate ease-in-out`; + container.appendChild(star); + } + + function createShootingStar() { + const star = document.createElement("div"); + star.classList.add("shooting-star"); + + let x = Math.random() * window.innerWidth * 0.8; + let y = Math.random() * window.innerHeight * 0.3; + const angle = Math.random() * Math.PI / 6 + Math.PI / 8; + const speed = 10; + const totalFrames = 60; + + const deg = angle * (180 / Math.PI); + star.style.left = `${x}px`; + star.style.top = `${y}px`; + star.style.transform = `rotate(${deg}deg)`; + + container.appendChild(star); + + let frame = 0; + function animate() { + x += Math.cos(angle) * speed; + y += Math.sin(angle) * speed; + star.style.left = `${x}px`; + star.style.top = `${y}px`; + star.style.opacity = `${1 - frame / totalFrames}`; + + frame++; + if (frame < totalFrames) { + requestAnimationFrame(animate); + } else { + container.removeChild(star); + } + } + + animate(); + } + + setInterval(() => { + if (Math.random() < 0.3) createShootingStar(); + }, 1000); +}); diff --git a/src/routes/[id].ts b/src/routes/[id].ts index cef0edf..089c7c2 100644 --- a/src/routes/[id].ts +++ b/src/routes/[id].ts @@ -59,12 +59,15 @@ async function handler(request: ExtendedRequest): Promise { mobile: presence.active_on_discord_mobile, web: presence.active_on_discord_web, }, - instance, - readme, - allowSnow: presence.kv.snow === "true", - allowRain: presence.kv.rain === "true", - colors: colors?.colors ?? {}, + instance: instance, + readme: readme, badgeApi: badgeApi, + colors: colors?.colors ?? {}, + extraOptions: { + snow: presence.kv.snow === "true", + rain: presence.kv.rain === "true", + stars: presence.kv.stars === "true", + } }; return await renderEjsTemplate("index", ejsTemplateData); diff --git a/src/routes/index.ts b/src/routes/index.ts index 1359239..257bc3c 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -58,12 +58,15 @@ async function handler(): Promise { mobile: presence.active_on_discord_mobile, web: presence.active_on_discord_web, }, - instance, - readme, - allowSnow: presence.kv.snow === "true", - allowRain: presence.kv.rain === "true", - colors: colors?.colors ?? {}, + instance: instance, + readme: readme, badgeApi: badgeApi, + colors: colors?.colors ?? {}, + extraOptions: { + snow: presence.kv.snow === "true", + rain: presence.kv.rain === "true", + stars: presence.kv.stars === "true", + } }; return await renderEjsTemplate("index", ejsTemplateData); diff --git a/src/views/index.ejs b/src/views/index.ejs index 9ba151d..6f16fea 100644 --- a/src/views/index.ejs +++ b/src/views/index.ejs @@ -19,12 +19,15 @@ - <% if (allowSnow) { %> + <% if (extraOptions.snow) { %> <% } %> - <% if(allowRain) { %> + <% if(extraOptions.rain) { %> <% } %> + <% if (extraOptions.stars) { %> + + <% } %>