Remove standalone services (ai-compliance-sdk root, developer-portal, dsms-gateway, dsms-node, night-scheduler) and legacy compliance/dsgvo pages. Add new SDK pipeline modules (academy, document-crawler, dsb-portal, incidents, whistleblower, reporting, sso, multi-tenant, industry-templates). Add drafting engine, legal corpus files (AT/CH/DE), pitch-deck, blog and Förderantrag pages. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
84 lines
1.9 KiB
TypeScript
84 lines
1.9 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useRef } from 'react'
|
|
|
|
interface Particle {
|
|
x: number
|
|
y: number
|
|
size: number
|
|
speed: number
|
|
opacity: number
|
|
}
|
|
|
|
export default function ParticleBackground() {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
|
const particlesRef = useRef<Particle[]>([])
|
|
const frameRef = useRef<number>(0)
|
|
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current
|
|
if (!canvas) return
|
|
|
|
const ctx = canvas.getContext('2d')
|
|
if (!ctx) return
|
|
|
|
function resize() {
|
|
canvas!.width = window.innerWidth
|
|
canvas!.height = window.innerHeight
|
|
}
|
|
|
|
function initParticles() {
|
|
const count = Math.min(150, Math.floor((window.innerWidth * window.innerHeight) / 8000))
|
|
particlesRef.current = Array.from({ length: count }, () => ({
|
|
x: Math.random() * canvas!.width,
|
|
y: Math.random() * canvas!.height,
|
|
size: Math.random() * 1.5 + 0.5,
|
|
speed: Math.random() * 0.3 + 0.1,
|
|
opacity: Math.random() * 0.5 + 0.1,
|
|
}))
|
|
}
|
|
|
|
function animate() {
|
|
if (!ctx || !canvas) return
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
|
|
for (const p of particlesRef.current) {
|
|
p.y -= p.speed
|
|
if (p.y < -10) {
|
|
p.y = canvas.height + 10
|
|
p.x = Math.random() * canvas.width
|
|
}
|
|
|
|
ctx.beginPath()
|
|
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2)
|
|
ctx.fillStyle = `rgba(255, 255, 255, ${p.opacity})`
|
|
ctx.fill()
|
|
}
|
|
|
|
frameRef.current = requestAnimationFrame(animate)
|
|
}
|
|
|
|
resize()
|
|
initParticles()
|
|
animate()
|
|
|
|
window.addEventListener('resize', () => {
|
|
resize()
|
|
initParticles()
|
|
})
|
|
|
|
return () => {
|
|
cancelAnimationFrame(frameRef.current)
|
|
window.removeEventListener('resize', resize)
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<canvas
|
|
ref={canvasRef}
|
|
className="fixed inset-0 pointer-events-none z-0"
|
|
style={{ opacity: 0.6 }}
|
|
/>
|
|
)
|
|
}
|