|
| 1 | +<script> |
| 2 | + import { onMount } from "svelte"; |
| 3 | +
|
| 4 | + let snowflakes = []; |
| 5 | + const SNOWFLAKE_COUNT = 100; |
| 6 | +
|
| 7 | + // Generate random snowflake properties |
| 8 | + function createSnowflake() { |
| 9 | + return { |
| 10 | + id: Math.random().toString(36).substring(7), |
| 11 | + x: Math.random() * 100, // Percentage |
| 12 | + y: -Math.random() * 100, // Start above view |
| 13 | + size: Math.random() * 50, // Size between 2 and 6 px |
| 14 | + speed: Math.random() * (0.3 - 0.1) + 0.1, // Falling speed |
| 15 | + swing: Math.random() * 10 + 2, // Horizontal movement |
| 16 | + }; |
| 17 | + } |
| 18 | +
|
| 19 | + // Initialize snowflakes |
| 20 | + onMount(() => { |
| 21 | + snowflakes = Array.from({ length: SNOWFLAKE_COUNT }, createSnowflake); |
| 22 | + }); |
| 23 | +
|
| 24 | + // Update snowflakes' position |
| 25 | + function updateSnowflakes() { |
| 26 | + snowflakes = snowflakes.map((flake) => { |
| 27 | + let newY = flake.y + flake.speed; |
| 28 | + let newX = |
| 29 | + flake.x + Math.sin((flake.y / 100) * Math.PI) * flake.swing * 0.01; |
| 30 | + let newSpeed = flake.speed |
| 31 | +
|
| 32 | + if (newY > 100 || newX > 100) { |
| 33 | + newY = 0 |
| 34 | + newX = Math.random() * 100 |
| 35 | + newSpeed = Math.random() * (0.3 - 0.1) + 0.1 |
| 36 | + } |
| 37 | + // if (newX > 100 ) { |
| 38 | + // |
| 39 | + // } |
| 40 | +
|
| 41 | + return { ...flake, x: newX, y: newY, speed: newSpeed }; |
| 42 | + }); |
| 43 | + } |
| 44 | +
|
| 45 | + // Animation loop |
| 46 | + let animationFrame; |
| 47 | + const loop = () => { |
| 48 | + updateSnowflakes(); |
| 49 | + animationFrame = requestAnimationFrame(loop); |
| 50 | + }; |
| 51 | +
|
| 52 | + onMount(() => { |
| 53 | + loop(); |
| 54 | + return () => cancelAnimationFrame(animationFrame); |
| 55 | + }); |
| 56 | +</script> |
| 57 | + |
| 58 | +<style> |
| 59 | + .snowfall-overlay { |
| 60 | + position: fixed; |
| 61 | + top: 0; |
| 62 | + left: 0; |
| 63 | + width: 100vw; |
| 64 | + height: 100vh; |
| 65 | + pointer-events: none; /* Allows interactions with underlying UI */ |
| 66 | + overflow: hidden; |
| 67 | + z-index: 9999; /* Ensure it overlays everything */ |
| 68 | + } |
| 69 | +
|
| 70 | + /*.snowflake {*/ |
| 71 | + /* !*width: 10px;*!*/ |
| 72 | + /* !*height: 10px;*!*/ |
| 73 | + /* background: none;*/ |
| 74 | + /* border: none;*/ |
| 75 | + /* position: absolute;*/ |
| 76 | + /* pointer-events: none;*/ |
| 77 | + /* color: #4cd5ff; !* Light blue color *!*/ |
| 78 | + /* !*font-size: 16px;*!*/ |
| 79 | + /* text-shadow: 0 0 5px rgba(173, 216, 230, 0.8);*/ |
| 80 | + /*}*/ |
| 81 | + .snowflake { |
| 82 | + position: absolute; |
| 83 | + color: #add8e6; /* Light blue color */ |
| 84 | + text-shadow: 0 0 5px rgba(173, 216, 230, 0.8); |
| 85 | + pointer-events: none; |
| 86 | + } |
| 87 | +
|
| 88 | + /*.snowflake::before {*/ |
| 89 | + /* content: "❄"; !* Unicode snowflake character *!*/ |
| 90 | + /* display: inline-block;*/ |
| 91 | + /*}*/ |
| 92 | +</style> |
| 93 | + |
| 94 | +<div class="snowfall-overlay"> |
| 95 | + {#each snowflakes as { id, x, y, size }} |
| 96 | + <div |
| 97 | + class="snowflake" |
| 98 | + style="transform: translate({x}vw, {y}vh); font-size: {size}px;" |
| 99 | +> |
| 100 | + ❄ |
| 101 | +</div> |
| 102 | + |
| 103 | +<!-- <div--> |
| 104 | +<!-- class="snowflake"--> |
| 105 | +<!-- style="transform: translate({x}vw, {y}vh); width: {size}px; height: {size}px;"--> |
| 106 | +<!-- ></div>--> |
| 107 | + {/each} |
| 108 | +</div> |
0 commit comments