48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
"use client"
|
|
|
|
import { useMemo } from "react"
|
|
|
|
interface Star {
|
|
left: number
|
|
top: number
|
|
size: number
|
|
delay: number
|
|
duration: number
|
|
}
|
|
|
|
export function StarField() {
|
|
const stars = useMemo<Star[]>(() => {
|
|
const result: Star[] = []
|
|
for (let i = 0; i < 160; i++) {
|
|
result.push({
|
|
left: Math.random() * 100,
|
|
top: Math.random() * 100,
|
|
size: 1.5 + Math.random() * 2,
|
|
delay: Math.random() * 6,
|
|
duration: 3 + Math.random() * 4,
|
|
})
|
|
}
|
|
return result
|
|
}, [])
|
|
|
|
return (
|
|
<div className="fixed inset-0 pointer-events-none select-none z-0 overflow-hidden">
|
|
{stars.map((s, i) => (
|
|
<div
|
|
key={i}
|
|
className="absolute rounded-full bg-[#222222] dark:bg-white star-twinkle"
|
|
style={{
|
|
left: `${s.left}%`,
|
|
top: `${s.top}%`,
|
|
width: `${s.size}px`,
|
|
height: `${s.size}px`,
|
|
opacity: 0.35 + Math.random() * 0.45,
|
|
animationDelay: `${s.delay}s`,
|
|
animationDuration: `${s.duration}s`,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|