From 35d7d05ee8a35cf2fcb109394e97b7962fa4d0a6 Mon Sep 17 00:00:00 2001 From: dawn <90008@klbr.net> Date: Tue, 16 Jun 2026 04:41:16 +0300 Subject: [PATCH] bg anim thing --- src/App.tsx | 43 +++++++++++++++++++++++++++++++++++++++++++ src/index.css | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/App.tsx b/src/App.tsx index d0743b4..a0e3a74 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,6 +23,30 @@ import Settings from "./components/Settings"; import MicRecorder from "./components/MicRecorder"; import { Link } from "./components/ui/link"; +// Pre-compute waveform SVG paths at module load (viewBox: 200 wide × 100 tall). +// translateX(-50%) on a 200%-wide SVG scrolls exactly one screen width → seamless loop. +const makeSinePath = (y: number, amp: number, λ: number): string => { + let d = `M0,${y}`; + for (let x = 0.5; x <= 200.5; x += 0.5) { + d += ` L${x.toFixed(1)},${(y + amp * Math.sin((2 * Math.PI * x) / λ)).toFixed(2)}`; + } + return d; +}; + +// Each track: y position (0-100), amplitude, wavelength, scroll speed, delay, opacity weight. +// λ must divide 100 (the scroll offset in viewBox units) for a seamless loop: +// sin(2π × 100/λ) = sin(0) only when 100/λ is a whole number → λ ∈ {20, 25, 50, …} +const WAVE_TRACKS = [ + { d: makeSinePath(10, 2.0, 20), dur: '30s', delay: '0s', op: 0.90 }, + { d: makeSinePath(22, 3.2, 25), dur: '44s', delay: '-8s', op: 0.55 }, + { d: makeSinePath(34, 1.5, 20), dur: '24s', delay: '-14s', op: 1.00 }, + { d: makeSinePath(46, 3.5, 25), dur: '38s', delay: '-5s', op: 0.50 }, + { d: makeSinePath(56, 2.0, 20), dur: '33s', delay: '-20s', op: 0.80 }, + { d: makeSinePath(68, 2.8, 50), dur: '52s', delay: '-12s', op: 0.45 }, + { d: makeSinePath(79, 1.8, 25), dur: '28s', delay: '-18s', op: 0.70 }, + { d: makeSinePath(90, 2.2, 20), dur: '36s', delay: '-3s', op: 0.60 }, +]; + const App = () => { const collection = () => createListCollection({ @@ -91,6 +115,25 @@ const App = () => { return ( <> +