'use client' import { useEffect, useRef } from 'react' export default function DotWaves() { const canvasRef = useRef(null) useEffect(() => { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') if (!ctx) return // Устанавливаем размеры canvas равными размерам контейнера const resizeCanvas = () => { const container = canvas.parentElement if (container) { canvas.width = container.offsetWidth canvas.height = container.offsetHeight } } resizeCanvas() window.addEventListener('resize', resizeCanvas) // Параметры анимации const dots: { x: number; y: number; z: number }[] = [] const numberOfDots = 200 // Больше точек для лучшего эффекта const maxDepth = 1000 // Максимальная глубина по Z const speed = 10 // Скорость движения // Создаем точки со случайными позициями в 3D пространстве for (let i = 0; i < numberOfDots; i++) { dots.push({ x: (Math.random() - 0.5) * canvas.width * 2, y: (Math.random() - 0.5) * canvas.height * 2, z: Math.random() * maxDepth, }) } // Анимация let animationFrameId: number const animate = () => { ctx.fillStyle = 'rgba(0, 0, 0, 0.2)' ctx.fillRect(0, 0, canvas.width, canvas.height) const centerX = canvas.width / 2 const centerY = canvas.height / 2 // Рисуем точки dots.forEach((dot) => { // Движение к наблюдателю (уменьшаем Z) dot.z = dot.z - speed // Если точка слишком близко, перемещаем её обратно вдаль if (dot.z <= 1) { dot.z = maxDepth dot.x = (Math.random() - 0.5) * canvas.width * 2 dot.y = (Math.random() - 0.5) * canvas.height * 2 } // Проецируем 3D координаты на 2D экран const scale = maxDepth / (maxDepth + dot.z) const x2d = centerX + dot.x * scale const y2d = centerY + dot.y * scale // Размер и яркость зависят от Z-координаты const size = Math.max(0.5, 2 * scale) const alpha = Math.min(1, scale * 1.5) ctx.beginPath() ctx.arc(x2d, y2d, size, 0, Math.PI * 2) ctx.fillStyle = `rgba(255, 255, 255, ${alpha})` ctx.fill() }) animationFrameId = requestAnimationFrame(animate) } animate() // Очистка return () => { window.removeEventListener('resize', resizeCanvas) cancelAnimationFrame(animationFrameId) } }, []) return ( ) }