diff --git a/bun.lockb b/bun.lockb index 0e37e6f..5399fde 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index f77d0a7..4d5206a 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,7 @@ "@astrojs/check": "^0.9.4", "@biomejs/biome": "1.9.4", "@tailwindcss/vite": "^4.0.0-beta.8", - "prettier": "^3.3.3", "tailwindcss": "^4.0.0-beta.8", "typescript": "^5.6.3" - }, - "trustedDependencies": ["@biomejs/biome", "@parcel/watcher", "@tsparticles/engine", "esbuild", "sharp"] + } } diff --git a/public/fonts/SF-Pro.woff2 b/public/fonts/SF-Pro.woff2 deleted file mode 100644 index 6e09361..0000000 Binary files a/public/fonts/SF-Pro.woff2 and /dev/null differ diff --git a/src/css/app.css b/src/css/app.css index 6a4609d..a461c50 100644 --- a/src/css/app.css +++ b/src/css/app.css @@ -1,13 +1 @@ -@import "tailwindcss"; - -@theme { - --font-sfpro: "sf-pro", sans-serif; -} - -@font-face { - font-family: "sf-pro"; - src: url("/fonts/SF-Pro.woff2") format("woff2"); - font-weight: normal; - font-style: normal; - font-display: block; -} \ No newline at end of file +@import "tailwindcss"; \ No newline at end of file diff --git a/src/js/snow.ts b/src/js/snow.ts new file mode 100644 index 0000000..996f0b2 --- /dev/null +++ b/src/js/snow.ts @@ -0,0 +1,89 @@ +interface Snowflake { + x: number; + y: number; + size: number; + opacity: number; + speedY: number; + speedX: number; +} + +function createSnowfall() { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d")!; + document.body.style.margin = "0"; + document.body.style.overflow = "hidden"; + canvas.style.position = "fixed"; + canvas.style.top = "0"; + canvas.style.left = "0"; + canvas.style.zIndex = "-1"; + + document.body.appendChild(canvas); + + const resizeCanvas = () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + }; + resizeCanvas(); + window.addEventListener("resize", resizeCanvas); + + const NUM_SNOWFLAKES = 320; + const snowflakes: Snowflake[] = []; + + let windStrength = 0; + + for (let i = 0; i < NUM_SNOWFLAKES; i++) { + snowflakes.push(createSnowflake()); + } + + function createSnowflake(): Snowflake { + const size = Math.random() * 3 + 1; + return { + x: Math.random() * canvas.width, + y: Math.random() * canvas.height, + size, + opacity: Math.random() * 0.2 + 0.2, + speedY: Math.random() * size * 0.6 + 0.4, + speedX: Math.random() * 0.5 - 0.25, + }; + } + + function updateWind() { + windStrength += (Math.random() - 0.5) * 0.01; + windStrength = Math.max(-0.5, Math.min(0.5, windStrength)); + } + + function updateSnowflakes() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + updateWind(); + + for (const flake of snowflakes) { + flake.x += flake.speedX + windStrength; + flake.y += flake.speedY; + + if (flake.y > canvas.height) { + flake.y = -flake.size; + flake.x = Math.random() * canvas.width; + flake.speedY = Math.random() * flake.size * 0.5 + 0.5; + flake.speedX = Math.random() * 0.5 - 0.25; + } + + if (flake.x < -flake.size) { + flake.x = canvas.width + flake.size; + } else if (flake.x > canvas.width + flake.size) { + flake.x = -flake.size; + } + + ctx.beginPath(); + ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2); + ctx.fillStyle = `rgba(255, 255, 255, ${flake.opacity})`; + ctx.fill(); + } + + requestAnimationFrame(updateSnowflakes); + } + + updateSnowflakes(); +} + +createSnowfall(); diff --git a/src/js/snowflakes.ts b/src/js/snowflakes.ts deleted file mode 100644 index 15be66f..0000000 --- a/src/js/snowflakes.ts +++ /dev/null @@ -1,79 +0,0 @@ -class SnowEffect { - private canvas: HTMLCanvasElement; - private ctx: CanvasRenderingContext2D; - private flakes: Array<[number, number, number, number, number]>; // [x, y, radius, drop, sway] - - constructor(flakeCount = 320) { - this.canvas = document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d")!; - this.flakes = []; - - this.initCanvas(); - this.initFlakes(flakeCount); - this.animate = this.animate.bind(this); - - window.addEventListener("resize", () => this.updateCanvasSize()); - requestAnimationFrame(this.animate); - } - - private initCanvas(): void { - this.canvas.style.cssText = - "position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:999"; - document.body.appendChild(this.canvas); - this.updateCanvasSize(); - } - - private updateCanvasSize(): void { - this.canvas.width = window.innerWidth; - this.canvas.height = window.innerHeight; - } - - private initFlakes(count: number): void { - const { width, height } = this.canvas; - this.flakes = Array.from({ length: count }, () => [ - Math.random() * width, // x - Math.random() * height, // y - Math.random() * 1.75 + 0.25, // radius - Math.random() * 1.5 + 0.5, // drop speed - Math.random() * 0.6 - 0.3, // sway - ]); - } - - private animate(): void { - const { width, height } = this.canvas; - - // Clear canvas - this.ctx.clearRect(0, 0, width, height); - - // Draw flakes - this.ctx.fillStyle = "rgba(255, 255, 255, 0.4)"; - this.ctx.beginPath(); - - // Update and draw flakes - for (const flake of this.flakes) { - // Update position - flake[1] += flake[3]; // y += drop - flake[0] += flake[4]; // x += sway - - // Wrap horizontally - if (flake[0] > width) flake[0] -= width; - else if (flake[0] < 0) flake[0] += width; - - // Reset when below screen - if (flake[1] > height) { - flake[1] = -flake[2]; - flake[0] = Math.random() * width; - } - - // Draw flake - this.ctx.moveTo(flake[0], flake[1]); - this.ctx.arc(flake[0], flake[1], flake[2], 0, Math.PI * 2); - } - - this.ctx.fill(); - requestAnimationFrame(this.animate); - } -} - -// start -new SnowEffect(); diff --git a/src/pages/404.astro b/src/pages/404.astro index bd1a182..792c2bc 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -11,16 +11,14 @@ import "/src/css/app.css"; -