Download AmbientParticles.tsx from metarm/QMetaRam: direct link, hf CLI and curl.
- Browser
- Download file 1.77 kB
-
https://huggingface.co/metarm/QMetaRam/resolve/main/AmbientParticles.tsx
- Command line
-
hf download hf://metarm/QMetaRam/AmbientParticles.tsx
-
curl -L -o AmbientParticles.tsx https://huggingface.co/metarm/QMetaRam/resolve/main/AmbientParticles.tsx
1.77 kB
| import { useEffect, useRef } from "react"; | |
| /** Floating atmospheric dust — pure CSS-cheap canvas pass. */ | |
| export function AmbientParticles() { | |
| const ref = useRef<HTMLCanvasElement>(null); | |
| useEffect(() => { | |
| const c = ref.current!; | |
| const ctx = c.getContext("2d")!; | |
| let raf = 0, w = 0, h = 0; | |
| const dpr = Math.min(window.devicePixelRatio || 1, 2); | |
| const particles: { x: number; y: number; vx: number; vy: number; r: number; a: number }[] = []; | |
| function resize() { | |
| const r = c.getBoundingClientRect(); | |
| w = r.width; h = r.height; | |
| c.width = w * dpr; c.height = h * dpr; | |
| ctx.setTransform(dpr, 0, 0, dpr, 0, 0); | |
| particles.length = 0; | |
| const n = Math.floor((w * h) / 28000); | |
| for (let i = 0; i < n; i++) { | |
| particles.push({ | |
| x: Math.random() * w, y: Math.random() * h, | |
| vx: (Math.random() - 0.5) * 0.15, | |
| vy: (Math.random() - 0.5) * 0.15 - 0.05, | |
| r: 0.4 + Math.random() * 1.2, | |
| a: 0.1 + Math.random() * 0.3, | |
| }); | |
| } | |
| } | |
| resize(); | |
| const ro = new ResizeObserver(resize); ro.observe(c); | |
| function tick() { | |
| raf = requestAnimationFrame(tick); | |
| ctx.clearRect(0, 0, w, h); | |
| for (const p of particles) { | |
| p.x += p.vx; p.y += p.vy; | |
| if (p.x < 0) p.x = w; if (p.x > w) p.x = 0; | |
| if (p.y < 0) p.y = h; if (p.y > h) p.y = 0; | |
| ctx.fillStyle = `hsla(220, 80%, 90%, ${p.a})`; | |
| ctx.beginPath(); | |
| ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); | |
| ctx.fill(); | |
| } | |
| } | |
| raf = requestAnimationFrame(tick); | |
| return () => { cancelAnimationFrame(raf); ro.disconnect(); }; | |
| }, []); | |
| return <canvas ref={ref} className="absolute inset-0 w-full h-full pointer-events-none" aria-hidden />; | |
| } | |