Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions LandingPage/src/Pages/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SpotlightCard from '../components/card';
import Header from '../components/Header';
import HowItWorks from '../components/howitworks';
import Integrations from '../components/integration';
import ParticleEffect from '../components/ParticleCanva';


function Landing() {
Expand All @@ -29,6 +30,7 @@ function Landing() {
};
return (
<div className="min-h-screen bg-black text-white">
<ParticleEffect />
<Header/>
{/* Hero Section */}

Expand Down
2 changes: 2 additions & 0 deletions LandingPage/src/Pages/Legal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
import Navbar from '../components/Header';
import Footer from '../components/Footer';
import { motion } from 'framer-motion';
import ParticleEffect from '../components/ParticleCanva';

const TermsOfService: React.FC = () => {
useEffect(() => {
Expand All @@ -11,6 +12,7 @@ const TermsOfService: React.FC = () => {

return (
<div className="min-h-screen bg-black text-white">
<ParticleEffect />
<Navbar />
<main className="pt-24 pb-16">
<div className="container mx-auto px-6">
Expand Down
4 changes: 3 additions & 1 deletion LandingPage/src/Pages/Privacy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
import Navbar from '../components/Header';
import Footer from '../components/Footer';
import { motion } from 'framer-motion';
import ParticleEffect from '../components/ParticleCanva';

const PrivacyPolicy: React.FC = () => {
useEffect(() => {
Expand All @@ -10,7 +11,8 @@ const PrivacyPolicy: React.FC = () => {
}, []);

return (
<div className="min-h-screen bg-black">
<div className="min-h-screen bg-black">
<ParticleEffect />
<Navbar />
<main className="pt-24 pb-16">
<div className="container mx-auto px-6">
Expand Down
213 changes: 213 additions & 0 deletions LandingPage/src/components/ParticleCanva.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React, { useEffect, useRef } from 'react';

interface Particle {
x: number;
y: number;
vx: number;
vy: number;
size: number;
opacity: number;
color: string;
life: number;
maxLife: number;
}

interface ParticleEffectProps {
particleCount?: number;
colors?: string[];
enableMouseInteraction?: boolean;
}

const ParticleEffect: React.FC<ParticleEffectProps> = ({
particleCount = 50,
colors = ['rgba(147, 0, 160, 0.8)', 'rgba(168, 85, 247, 0.6)', 'rgba(236, 72, 153, 0.7)', 'rgba(255, 255, 255, 0.4)'],
enableMouseInteraction = true,
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const animationRef = useRef<number>(0);
const particlesRef = useRef<Particle[]>([]);
const mouseRef = useRef({ x: 0, y: 0 });

useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;

const ctx = canvas.getContext('2d');
if (!ctx) return;

const resizeCanvas = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};

const createParticle = (): Particle => {
const maxLife = Math.random() * 200 + 100;
return {
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.5,
vy: (Math.random() - 0.5) * 0.5,
size: Math.random() * 3 + 1,
opacity: Math.random() * 0.8 + 0.2,
color: colors[Math.floor(Math.random() * colors.length)],
life: maxLife,
maxLife: maxLife,
};
};

const initParticles = () => {
particlesRef.current = [];
for (let i = 0; i < particleCount; i++) {
particlesRef.current.push(createParticle());
}
};

const handleMouseMove = (e: MouseEvent) => {
const rect = canvas.getBoundingClientRect();
mouseRef.current.x = e.clientX - rect.left;
mouseRef.current.y = e.clientY - rect.top;
};

const drawParticle = (particle: Particle) => {
ctx.save();

// Create gradient for each particle
const gradient = ctx.createRadialGradient(
particle.x, particle.y, 0,
particle.x, particle.y, particle.size * 2
);
gradient.addColorStop(0, particle.color);
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');

ctx.fillStyle = gradient;
ctx.globalAlpha = particle.opacity * (particle.life / particle.maxLife);

ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
ctx.fill();

// Add a subtle glow effect
ctx.shadowBlur = 10;
ctx.shadowColor = particle.color;
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.size * 0.5, 0, Math.PI * 2);
ctx.fill();

ctx.restore();
};

const updateParticle = (particle: Particle) => {
// Mouse interaction
if (enableMouseInteraction) {
const dx = mouseRef.current.x - particle.x;
const dy = mouseRef.current.y - particle.y;
const distance = Math.sqrt(dx * dx + dy * dy);

if (distance < 150) {
const force = (150 - distance) / 150;
particle.vx += (dx / distance) * force * 0.002;
particle.vy += (dy / distance) * force * 0.002;
}
}

// Update position
particle.x += particle.vx;
particle.y += particle.vy;

// Apply subtle drift
particle.vx *= 0.99;
particle.vy *= 0.99;

// Add floating motion
particle.x += Math.sin(Date.now() * 0.001 + particle.y * 0.01) * 0.1;
particle.y += Math.cos(Date.now() * 0.001 + particle.x * 0.01) * 0.1;
Comment on lines +122 to +123
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid using Date.now() in animation calculations.

Using Date.now() in the floating motion calculation can cause performance issues as it's called for every particle on every frame. Consider using a frame counter or elapsed time instead.

Apply this diff to improve performance:

+  const animationRef = useRef<number>(0);
+  const timeRef = useRef<number>(0);

   // In animate function:
+  timeRef.current += 0.016; // Approximate 60fps

   // In updateParticle:
-  particle.x += Math.sin(Date.now() * 0.001 + particle.y * 0.01) * 0.1;
-  particle.y += Math.cos(Date.now() * 0.001 + particle.x * 0.01) * 0.1;
+  particle.x += Math.sin(timeRef.current + particle.y * 0.01) * 0.1;
+  particle.y += Math.cos(timeRef.current + particle.x * 0.01) * 0.1;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
particle.x += Math.sin(Date.now() * 0.001 + particle.y * 0.01) * 0.1;
particle.y += Math.cos(Date.now() * 0.001 + particle.x * 0.01) * 0.1;
particle.x += Math.sin(timeRef.current + particle.y * 0.01) * 0.1;
particle.y += Math.cos(timeRef.current + particle.x * 0.01) * 0.1;
🤖 Prompt for AI Agents
In LandingPage/src/components/ParticleCanva.tsx around lines 122 to 123, replace
the use of Date.now() in the particle position updates with a frame counter or
elapsed time variable that updates once per animation frame. This avoids calling
Date.now() for every particle on every frame, improving performance. Introduce a
time variable outside the particle loop that increments each frame and use it in
the sine and cosine calculations instead of Date.now().


// Boundary wrapping
if (particle.x < -particle.size) particle.x = canvas.width + particle.size;
if (particle.x > canvas.width + particle.size) particle.x = -particle.size;
if (particle.y < -particle.size) particle.y = canvas.height + particle.size;
if (particle.y > canvas.height + particle.size) particle.y = -particle.size;

// Update life
particle.life -= 0.5;
if (particle.life <= 0) {
// Regenerate particle
const newParticle = createParticle();
Object.assign(particle, newParticle);
}
};

const drawConnections = () => {
const particles = particlesRef.current;
ctx.strokeStyle = 'rgba(147, 0, 160, 0.1)';
ctx.lineWidth = 0.5;

for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x;
const dy = particles[i].y - particles[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);

if (distance < 100) {
const opacity = (100 - distance) / 100 * 0.3;
ctx.globalAlpha = opacity;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.stroke();
}
}
}
ctx.globalAlpha = 1;
};
Comment on lines +140 to +162
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

O(n²) complexity in connection drawing may impact performance.

The nested loop for drawing connections has quadratic complexity. With the default 50 particles, this results in 1,225 distance calculations per frame. Consider implementing spatial partitioning or limiting connections to improve performance on lower-end devices.

🤖 Prompt for AI Agents
In LandingPage/src/components/ParticleCanva.tsx around lines 140 to 162, the
nested loops for drawing connections have O(n²) complexity, causing performance
issues with many particles. To fix this, implement spatial partitioning
techniques like a grid or quadtree to limit distance checks only to nearby
particles, or restrict the maximum number of connections per particle. This will
reduce the number of distance calculations and improve rendering performance on
lower-end devices.


const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Draw connections first (behind particles)
drawConnections();

// Update and draw particles
particlesRef.current.forEach(particle => {
updateParticle(particle);
drawParticle(particle);
});

animationRef.current = requestAnimationFrame(animate);
};

// Initialize
resizeCanvas();
initParticles();

// Event listeners
window.addEventListener('resize', resizeCanvas);
if (enableMouseInteraction) {
canvas.addEventListener('mousemove', handleMouseMove);
}

// Start animation
animate();

// Cleanup
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
window.removeEventListener('resize', resizeCanvas);
if (enableMouseInteraction) {
canvas.removeEventListener('mousemove', handleMouseMove);
}
};
}, [particleCount, colors, enableMouseInteraction]);

return (
<canvas
ref={canvasRef}
className="fixed inset-0 pointer-events-none z-[10]"
style={{ background: 'transparent' }}
/>
);
};

export default ParticleEffect;