Skip to content

Commit c31e5c6

Browse files
Fix issues in FloatingParticles.tsx
1 parent 84ad28e commit c31e5c6

1 file changed

Lines changed: 121 additions & 119 deletions

File tree

‎apps/codebility/app/(marketing)/_components/landing/FloatingParticles.tsx‎

Lines changed: 121 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

3-
import { useEffect, useRef } from "react";
4-
import { motion, useMotionValue, useSpring, useTransform } from "framer-motion";
3+
import { useEffect, useRef, useState } from "react";
4+
import { motion, useMotionValue, useSpring } from "framer-motion";
55

66
interface Particle {
77
id: number;
@@ -24,22 +24,36 @@ const FloatingParticles = () => {
2424
const mouseYSpring = useSpring(mouseY, { damping: 25, stiffness: 150 });
2525
const scrollYSpring = useSpring(scrollY, { damping: 30, stiffness: 100 });
2626

27-
// Create particles array
28-
const particles: Particle[] = Array.from({ length: 15 }, (_, i) => ({
29-
id: i,
30-
x: Math.random() * 100,
31-
y: Math.random() * 100,
32-
size: Math.random() * 8 + 4,
33-
color: [
27+
// State for particles - generated only on client
28+
const [particles, setParticles] = useState<Particle[]>([]);
29+
const [isMounted, setIsMounted] = useState(false);
30+
31+
// Generate particles on client side only
32+
useEffect(() => {
33+
const colors = [
3434
"rgba(147, 71, 255, 0.4)", // Purple
3535
"rgba(2, 255, 226, 0.3)", // Cyan
3636
"rgba(106, 120, 242, 0.3)", // Blue
3737
"rgba(255, 255, 255, 0.2)", // White
38-
][Math.floor(Math.random() * 4)],
39-
opacity: Math.random() * 0.5 + 0.2,
40-
speed: Math.random() * 0.5 + 0.2,
41-
direction: Math.random() * Math.PI * 2,
42-
}));
38+
];
39+
40+
const generatedParticles: Particle[] = Array.from({ length: 15 }, (_, i) => {
41+
const randomColorIndex = Math.floor(Math.random() * colors.length);
42+
return {
43+
id: i,
44+
x: Math.random() * 100,
45+
y: Math.random() * 100,
46+
size: Math.random() * 8 + 4,
47+
color: colors[randomColorIndex]!,
48+
opacity: Math.random() * 0.5 + 0.2,
49+
speed: Math.random() * 0.5 + 0.2,
50+
direction: Math.random() * Math.PI * 2,
51+
};
52+
});
53+
54+
setParticles(generatedParticles);
55+
setIsMounted(true);
56+
}, []);
4357

4458
useEffect(() => {
4559
const handleMouseMove = (e: MouseEvent) => {
@@ -65,130 +79,118 @@ const FloatingParticles = () => {
6579
};
6680
}, [mouseX, mouseY, scrollY]);
6781

82+
// Don't render particles until mounted on client
83+
if (!isMounted) {
84+
return (
85+
<div
86+
ref={containerRef}
87+
className="pointer-events-none absolute inset-0 overflow-hidden"
88+
style={{ zIndex: 1 }}
89+
/>
90+
);
91+
}
92+
6893
return (
6994
<div
7095
ref={containerRef}
7196
className="pointer-events-none absolute inset-0 overflow-hidden"
7297
style={{ zIndex: 1 }}
7398
>
74-
{particles.map((particle) => {
75-
const mouseInfluenceX = useTransform(
76-
mouseXSpring,
77-
[0, 1],
78-
[-20, 20]
79-
);
80-
const mouseInfluenceY = useTransform(
81-
mouseYSpring,
82-
[0, 1],
83-
[-20, 20]
84-
);
85-
const scrollInfluence = useTransform(
86-
scrollYSpring,
87-
[0, 1000],
88-
[0, -100]
89-
);
90-
91-
return (
99+
{particles.map((particle) => (
100+
<motion.div
101+
key={particle.id}
102+
className="absolute rounded-full"
103+
style={{
104+
width: particle.size,
105+
height: particle.size,
106+
backgroundColor: particle.color,
107+
left: `${particle.x}%`,
108+
top: `${particle.y}%`,
109+
opacity: particle.opacity,
110+
}}
111+
animate={{
112+
x: [0, Math.cos(particle.direction) * 30, 0],
113+
y: [0, Math.sin(particle.direction) * 30, 0],
114+
scale: [1, 1.2, 1],
115+
opacity: [particle.opacity, particle.opacity * 0.5, particle.opacity],
116+
}}
117+
transition={{
118+
duration: 8 + particle.speed * 4,
119+
repeat: Infinity,
120+
ease: "easeInOut",
121+
delay: particle.id * 0.2,
122+
}}
123+
>
124+
{/* Inner glow effect */}
92125
<motion.div
93-
key={particle.id}
94-
className="absolute rounded-full"
126+
className="absolute inset-0 rounded-full"
95127
style={{
96-
width: particle.size,
97-
height: particle.size,
98-
backgroundColor: particle.color,
99-
left: `${particle.x}%`,
100-
top: `${particle.y}%`,
101-
x: mouseInfluenceX,
102-
y: [mouseInfluenceY, scrollInfluence],
103-
opacity: particle.opacity,
128+
background: `radial-gradient(circle, ${particle.color} 0%, transparent 70%)`,
129+
filter: "blur(2px)",
104130
}}
105131
animate={{
106-
x: [0, Math.cos(particle.direction) * 30, 0],
107-
y: [0, Math.sin(particle.direction) * 30, 0],
108-
scale: [1, 1.2, 1],
109-
opacity: [particle.opacity, particle.opacity * 0.5, particle.opacity],
132+
scale: [1, 1.5, 1],
133+
opacity: [0.8, 0.3, 0.8],
110134
}}
111135
transition={{
112-
duration: 8 + particle.speed * 4,
136+
duration: 4 + particle.speed * 2,
113137
repeat: Infinity,
114138
ease: "easeInOut",
115-
delay: particle.id * 0.2,
139+
delay: particle.id * 0.1,
116140
}}
117-
>
118-
{/* Inner glow effect */}
119-
<motion.div
120-
className="absolute inset-0 rounded-full"
121-
style={{
122-
background: `radial-gradient(circle, ${particle.color} 0%, transparent 70%)`,
123-
filter: "blur(2px)",
124-
}}
125-
animate={{
126-
scale: [1, 1.5, 1],
127-
opacity: [0.8, 0.3, 0.8],
128-
}}
129-
transition={{
130-
duration: 4 + particle.speed * 2,
131-
repeat: Infinity,
132-
ease: "easeInOut",
133-
delay: particle.id * 0.1,
134-
}}
135-
/>
136-
</motion.div>
137-
);
138-
})}
141+
/>
142+
</motion.div>
143+
))}
139144

140145
{/* Additional floating orbs with mouse interaction */}
141-
{Array.from({ length: 8 }, (_, i) => {
142-
const orbMouseX = useTransform(
143-
mouseXSpring,
144-
[0, 1],
145-
[i * 30 - 120, i * 30 + 120]
146-
);
147-
const orbMouseY = useTransform(
148-
mouseYSpring,
149-
[0, 1],
150-
[i * 20 - 80, i * 20 + 80]
151-
);
152-
153-
return (
154-
<motion.div
155-
key={`orb-${i}`}
156-
className="absolute"
146+
{Array.from({ length: 8 }, (_, i) => (
147+
<motion.div
148+
key={`orb-${i}`}
149+
className="absolute"
150+
style={{
151+
left: `${20 + i * 10}%`,
152+
top: `${30 + (i % 3) * 20}%`,
153+
}}
154+
animate={{
155+
x: [0, (i * 30 - 120), (i * 30 + 120), 0],
156+
y: [0, (i * 20 - 80), (i * 20 + 80), 0],
157+
rotate: [0, 360],
158+
scale: [1, 1.1, 1],
159+
}}
160+
transition={{
161+
x: {
162+
duration: 15 + i * 2,
163+
repeat: Infinity,
164+
ease: "easeInOut",
165+
},
166+
y: {
167+
duration: 12 + i * 2,
168+
repeat: Infinity,
169+
ease: "easeInOut",
170+
},
171+
rotate: {
172+
duration: 20 + i * 2,
173+
repeat: Infinity,
174+
ease: "linear",
175+
},
176+
scale: {
177+
duration: 6 + i,
178+
repeat: Infinity,
179+
ease: "easeInOut",
180+
},
181+
}}
182+
>
183+
<div
184+
className="h-3 w-3 rounded-full"
157185
style={{
158-
left: `${20 + i * 10}%`,
159-
top: `${30 + (i % 3) * 20}%`,
160-
x: orbMouseX,
161-
y: orbMouseY,
162-
}}
163-
animate={{
164-
rotate: [0, 360],
165-
scale: [1, 1.1, 1],
166-
}}
167-
transition={{
168-
rotate: {
169-
duration: 20 + i * 2,
170-
repeat: Infinity,
171-
ease: "linear",
172-
},
173-
scale: {
174-
duration: 6 + i,
175-
repeat: Infinity,
176-
ease: "easeInOut",
177-
},
186+
background: `radial-gradient(circle, ${
187+
["rgba(147, 71, 255, 0.6)", "rgba(2, 255, 226, 0.4)"][i % 2]
188+
} 0%, transparent 70%)`,
189+
filter: "blur(1px)",
178190
}}
179-
>
180-
<div
181-
className="h-3 w-3 rounded-full"
182-
style={{
183-
background: `radial-gradient(circle, ${
184-
["rgba(147, 71, 255, 0.6)", "rgba(2, 255, 226, 0.4)"][i % 2]
185-
} 0%, transparent 70%)`,
186-
filter: "blur(1px)",
187-
}}
188-
/>
189-
</motion.div>
190-
);
191-
})}
191+
/>
192+
</motion.div>
193+
))}
192194

193195
{/* Ambient light orbs */}
194196
<motion.div

0 commit comments

Comments
 (0)