snowflake rewrite
This commit is contained in:
parent
39c53b1bd1
commit
b2b7360a65
11 changed files with 428 additions and 361 deletions
12
src/css/app.css
Normal file
12
src/css/app.css
Normal file
|
@ -0,0 +1,12 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: "sf-pro";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: url(/src/fonts/SF-Pro.woff2) format("woff2");
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes snowfall {
|
||||
0% {
|
||||
transform: translateY(-10vh);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(130vh);
|
||||
}
|
||||
}
|
||||
.snowflake {
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
position: fixed;
|
||||
top: -5vh;
|
||||
animation: snowfall infinite;
|
||||
opacity: 0.1;
|
||||
}
|
BIN
src/fonts/SF-Pro.woff2
Normal file
BIN
src/fonts/SF-Pro.woff2
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 339 KiB |
12
src/js/index.ts
Normal file
12
src/js/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { animate, stagger } from "motion";
|
||||
|
||||
const elements = document.querySelectorAll("img, h1");
|
||||
animate(
|
||||
elements,
|
||||
{ opacity: [0, 1] },
|
||||
{
|
||||
duration: 0.6,
|
||||
delay: stagger(0.6, { startDelay: 0.2 }),
|
||||
ease: "easeIn",
|
||||
},
|
||||
);
|
|
@ -1,27 +1,79 @@
|
|||
function createSnowflakes() {
|
||||
const numSnowflakes = 50;
|
||||
const maxSize = 0.2;
|
||||
const maxTranslate = 10;
|
||||
const container = document.getElementById('snowflake-container');
|
||||
function randomBetween(min, max) {
|
||||
return (Math.random() * max) + min;
|
||||
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);
|
||||
}
|
||||
if (container) {
|
||||
for (let i = 0; i < numSnowflakes; i++) {
|
||||
let randomSize = randomBetween(5, 25) + "px";
|
||||
let randomLeft = randomBetween(0, window.innerWidth) + "px";
|
||||
let randomDuration = randomBetween(3, 10);
|
||||
|
||||
const snowflake = document.createElement('div');
|
||||
snowflake.classList.add('snowflake');
|
||||
snowflake.style.width = randomSize;
|
||||
snowflake.style.height = randomSize;
|
||||
snowflake.style.left = randomLeft;
|
||||
snowflake.style.animationDuration = randomDuration + "s";
|
||||
snowflake.style.animationDelay = randomBetween(0, 5) + "s";
|
||||
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();
|
||||
}
|
||||
|
||||
container.appendChild(snowflake);
|
||||
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);
|
||||
}
|
||||
}
|
||||
createSnowflakes();
|
||||
|
||||
// start
|
||||
new SnowEffect();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import "./src/css/snowflake.css";
|
||||
import "./src/css/app.css";
|
||||
---
|
||||
|
||||
<html lang="en-us">
|
||||
|
@ -12,14 +12,15 @@ import "./src/css/snowflake.css";
|
|||
<link rel="icon" type="image/png" sizes="192x192" href="/src/img/logo_bg.svg" />
|
||||
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="/src/img/logo_bg.svg" />
|
||||
</head>
|
||||
<body class="bg-cover bg-[url('/src/img/gradient.webp')] text-white overflow-hidden">
|
||||
<body class="bg-gradient-to-b from-neutral-700 via-neutral-900 to-neutral-950 text-white overflow-hidden">
|
||||
<div class="flex items-center justify-center min-h-screen">
|
||||
<div class="bg-[rgba(11,11,11,0.6)] aspect-square rounded-3xl border-2 border-white flex flex-col items-center justify-center w-full h-full max-w-[60vmin] max-h-[60vmin] md:max-w-[35vmin] md:max-h-[35vmin]">
|
||||
<img class="w-2/3" src="/src/img/logo.svg" alt="logo" />
|
||||
<h1 class="text-4xl">z0x</h1>
|
||||
<div class="bg-black bg-opacity-40 aspect-square rounded-xl flex flex-col items-center justify-center w-full h-full max-w-[60vmin] max-h-[60vmin] md:max-w-[35vmin] md:max-h-[35vmin]">
|
||||
<img class="w-2/3 opacity-0" src="/src/img/logo.svg" alt="logo" />
|
||||
<h1 class="text-4xl opacity-0 font-sfpro font-semibold">z0x</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div id="snowflake-container"></div>
|
||||
<script src="/src/js/snowflakes.js"></script>
|
||||
<script src="/src/js/snowflakes.ts"></script>
|
||||
<script src="/src/js/index.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue