diff --git a/assets/js/index.js b/assets/js/index.js index 707d791..f056c0b 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -277,14 +277,19 @@ function fetchSong() { }); } -function fetchWeather(location) { +async function fetchWeather(location) { const target = document.getElementById('weather'); const query = location ? location : "Munich"; - fetch(`https://wttr.in/${query}?format=%t | %C`).then(response => response.text()).then(data => { + + try { + const response = await fetch(`https://wttr.in/${query}?format=%t | %C`); + const data = await response.text(); target.innerText = data; - }).catch(() => { + return data; + } catch { target.innerText = "Weather unavailable"; - }); + return null; + } } wakatime.fetchWakatime("#wakapi"); @@ -347,9 +352,20 @@ setInterval(() => { }, 50); typeWriter(); -fetchWeather(); fetchSong(); +const weather = await fetchWeather(); + +if (weather && weather.includes("rain")) { + const deco = document.createElement("script"); + deco.src = "/assets/js/rain.js"; + document.body.appendChild(deco); +} else if (weather.includes("snow")) { + const deco = document.createElement("script"); + deco.src = "/assets/js/snow.js"; + document.body.appendChild(deco); +} + let countdown = 60; setInterval(() => { diff --git a/assets/js/rain.js b/assets/js/rain.js new file mode 100644 index 0000000..1e51d6e --- /dev/null +++ b/assets/js/rain.js @@ -0,0 +1,88 @@ +const rainContainer = document.createElement("div"); +rainContainer.style.position = "fixed"; +rainContainer.style.top = "0"; +rainContainer.style.left = "0"; +rainContainer.style.width = "100vw"; +rainContainer.style.height = "100vh"; +rainContainer.style.pointerEvents = "none"; +document.body.appendChild(rainContainer); + +const maxRaindrops = 100; +const raindrops = []; +const mouse = { x: -100, y: -100 }; + +document.addEventListener("mousemove", (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; +}); + +const getRaindropColor = () => { + const htmlTag = document.documentElement; + return htmlTag.getAttribute("data-theme") === "dark" + ? "rgba(173, 216, 230, 0.8)" + : "rgba(70, 130, 180, 0.8)"; +}; + +const createRaindrop = () => { + if (raindrops.length >= maxRaindrops) { + const oldest = raindrops.shift(); + rainContainer.removeChild(oldest); + } + + const raindrop = document.createElement("div"); + raindrop.classList.add("raindrop"); + raindrop.style.position = "absolute"; + const height = Math.random() * 10 + 10; + raindrop.style.width = "2px"; + raindrop.style.height = `${height}px`; + raindrop.style.background = getRaindropColor(); + raindrop.style.borderRadius = "1px"; + raindrop.style.opacity = Math.random() * 0.5 + 0.3; + + raindrop.x = Math.random() * window.innerWidth; + raindrop.y = -height; + raindrop.speed = Math.random() * 6 + 4; + raindrop.directionX = (Math.random() - 0.5) * 0.2; + raindrop.directionY = Math.random() * 0.5 + 0.8; + + raindrop.style.left = `${raindrop.x}px`; + raindrop.style.top = `${raindrop.y}px`; + + raindrops.push(raindrop); + rainContainer.appendChild(raindrop); +}; + +setInterval(createRaindrop, 50); + +function updateRaindrops() { + raindrops.forEach((raindrop, index) => { + const height = Number.parseFloat(raindrop.style.height); + + raindrop.x += raindrop.directionX * raindrop.speed; + raindrop.y += raindrop.directionY * raindrop.speed; + + raindrop.style.left = `${raindrop.x}px`; + raindrop.style.top = `${raindrop.y}px`; + + if (raindrop.y > window.innerHeight) { + rainContainer.removeChild(raindrop); + raindrops.splice(index, 1); + return; + } + + if ( + raindrop.x > window.innerWidth || + raindrop.y > window.innerHeight || + raindrop.x < 0 + ) { + raindrop.x = Math.random() * window.innerWidth; + raindrop.y = -height; + raindrop.style.left = `${raindrop.x}px`; + raindrop.style.top = `${raindrop.y}px`; + } + }); + + requestAnimationFrame(updateRaindrops); +} + +updateRaindrops(); diff --git a/assets/js/snow.js b/assets/js/snow.js new file mode 100644 index 0000000..4d3e755 --- /dev/null +++ b/assets/js/snow.js @@ -0,0 +1,95 @@ +const snowContainer = document.createElement("div"); +snowContainer.style.position = "fixed"; +snowContainer.style.top = "0"; +snowContainer.style.left = "0"; +snowContainer.style.width = "100vw"; +snowContainer.style.height = "100vh"; +snowContainer.style.pointerEvents = "none"; +document.body.appendChild(snowContainer); + +const maxSnowflakes = 60; +const snowflakes = []; +const mouse = { x: -100, y: -100 }; + +document.addEventListener("mousemove", (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; +}); + +const createSnowflake = () => { + if (snowflakes.length >= maxSnowflakes) { + const oldestSnowflake = snowflakes.shift(); + snowContainer.removeChild(oldestSnowflake); + } + + const snowflake = document.createElement("div"); + snowflake.classList.add("snowflake"); + snowflake.style.position = "absolute"; + const size = Math.random() * 3 + 2; + snowflake.style.width = `${size}px`; + snowflake.style.height = `${size}px`; + snowflake.style.background = "white"; + snowflake.style.borderRadius = "50%"; + snowflake.style.opacity = Math.random(); + + snowflake.x = Math.random() * window.innerWidth; + snowflake.y = -size; + snowflake.speed = Math.random() * 3 + 2; + snowflake.directionX = (Math.random() - 0.5) * 0.5; + snowflake.directionY = Math.random() * 0.5 + 0.5; + + snowflake.style.left = `${snowflake.x}px`; + snowflake.style.top = `${snowflake.y}px`; + + snowflakes.push(snowflake); + snowContainer.appendChild(snowflake); +}; + +setInterval(createSnowflake, 80); + +function updateSnowflakes() { + snowflakes.forEach((snowflake, index) => { + const size = Number.parseFloat(snowflake.style.width); + const centerX = snowflake.x + size / 2; + const centerY = snowflake.y + size / 2; + + const dx = centerX - mouse.x; + const dy = centerY - mouse.y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < 30) { + snowflake.directionX += (dx / distance) * 0.02; + snowflake.directionY += (dy / distance) * 0.02; + } else { + snowflake.directionX += (Math.random() - 0.5) * 0.01; + snowflake.directionY += (Math.random() - 0.5) * 0.01; + } + + snowflake.x += snowflake.directionX * snowflake.speed; + snowflake.y += snowflake.directionY * snowflake.speed; + + snowflake.style.left = `${snowflake.x}px`; + snowflake.style.top = `${snowflake.y}px`; + + if (snowflake.y > window.innerHeight) { + snowContainer.removeChild(snowflake); + snowflakes.splice(index, 1); + return; + } + + if ( + snowflake.x > window.innerWidth || + snowflake.y > window.innerHeight || + snowflake.x < 0 + ) { + snowflake.x = Math.random() * window.innerWidth; + snowflake.y = -size; + snowflake.style.left = `${snowflake.x}px`; + snowflake.style.top = `${snowflake.y}px`; + } + }); + + requestAnimationFrame(updateSnowflakes); +} + +updateSnowflakes(); diff --git a/assets/js/stars.js b/assets/js/stars.js new file mode 100644 index 0000000..6fff4eb --- /dev/null +++ b/assets/js/stars.js @@ -0,0 +1,63 @@ +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"); + star.className = "star"; + const size = Math.random() * 2 + 1; + star.style.width = `${size}px`; + star.style.height = `${size}px`; + star.style.opacity = Math.random(); + star.style.top = `${Math.random() * 100}vh`; + star.style.left = `${Math.random() * 100}vw`; + star.style.animationDuration = `${Math.random() * 3 + 2}s`; + container.appendChild(star); +} + +function createShootingStar() { + const star = document.createElement("div"); + star.className = "shooting-star"; + + star.x = Math.random() * window.innerWidth * 0.8; + star.y = Math.random() * window.innerHeight * 0.3; + const angle = (Math.random() * Math.PI) / 6 + Math.PI / 8; + const speed = 10; + const totalFrames = 60; + let frame = 0; + + const deg = angle * (180 / Math.PI); + star.style.left = `${star.x}px`; + star.style.top = `${star.y}px`; + star.style.transform = `rotate(${deg}deg)`; + + container.appendChild(star); + + function animate() { + star.x += Math.cos(angle) * speed; + star.y += Math.sin(angle) * speed; + star.style.left = `${star.x}px`; + star.style.top = `${star.y}px`; + star.style.opacity = `${1 - frame / totalFrames}`; + + frame++; + if (frame < totalFrames) { + requestAnimationFrame(animate); + } else if (star.parentNode === container) { + container.removeChild(star); + } + } + + animate(); +} + +setInterval(() => { + if (Math.random() < 0.3) createShootingStar(); +}, 1000);