From bf3bf9cbbb528e8d2888b94d6f99ee19b6c595ac Mon Sep 17 00:00:00 2001 From: Dev-Sahad Date: Fri, 31 Jul 2026 09:52:03 +0400 Subject: [PATCH] add interactive 3d animated background --- src/components/AnimatedBackground.tsx | 114 +++------ src/components/three/BackgroundScene.tsx | 295 +++++++++++++++++++++++ 2 files changed, 335 insertions(+), 74 deletions(-) create mode 100644 src/components/three/BackgroundScene.tsx diff --git a/src/components/AnimatedBackground.tsx b/src/components/AnimatedBackground.tsx index 13a2608..e121d2a 100644 --- a/src/components/AnimatedBackground.tsx +++ b/src/components/AnimatedBackground.tsx @@ -1,85 +1,51 @@ 'use client' -import React, { useEffect, useMemo, useRef } from 'react' +import dynamic from 'next/dynamic' -const AnimatedBackground = () => { - const particles = useMemo(() => Array.from({ length: 36 }, (_, i) => ({ left: (i * 47) % 100, top: (i * 71) % 100, delay: (i % 9) * 0.38, depth: 0.55 + (i % 5) * 0.12 })), []) - const blobRefs = useRef<(HTMLDivElement | null)[]>([]) - - useEffect(() => { - let requestId: number - - const handleScroll = () => { - const scroll = window.pageYOffset - - blobRefs.current.forEach((blob, index) => { - if (!blob) return - - const xOffset = - Math.sin(scroll / 120 + index * 0.6) * 100 - - const yOffset = - Math.cos(scroll / 120 + index * 0.6) * 35 - - blob.style.transform = `translate(${xOffset}px, ${yOffset}px)` - blob.style.transition = 'transform 1.2s ease-out' - }) - - requestId = requestAnimationFrame(handleScroll) - } - - window.addEventListener('scroll', handleScroll) - handleScroll() - - return () => { - window.removeEventListener('scroll', handleScroll) - cancelAnimationFrame(requestId) - } - }, []) +const BackgroundScene = dynamic( + () => import('@/components/three/BackgroundScene'), + { ssr: false, loading: () => null }, +) +export default function AnimatedBackground() { return ( -
-
- {/* top left */} -
{ - blobRefs.current[0] = ref - }} - className="absolute top-10 left-10 w-40 h-40 md:w-56 md:h-56 rounded-full bg-white blur-[90px] opacity-30" - /> - - {/* top right */} -
{ - blobRefs.current[1] = ref - }} - className="absolute top-10 right-10 w-40 h-40 md:w-56 md:h-56 rounded-full bg-zinc-300 blur-[100px] opacity-25" - /> - - {/* bottom left */} -
{ - blobRefs.current[2] = ref - }} - className="absolute bottom-10 left-10 w-44 h-44 md:w-60 md:h-60 rounded-full bg-zinc-400 blur-[110px] opacity-30" - /> +