interface Props { // Color of the first set of particles (default: Ultramarine) primaryColor?: string; // Color of the second set of particles (default: Aqua) secondaryColor?: string; // Radius of mouse interaction (default: 150px) mouseRadius?: number; // Background color or gradient (default: Dark gradient) backgroundColor?: string; } export default function ParticleBackground({ primaryColor = "rgba(68, 116, 255, 0.8)", // Ultramarine secondaryColor = "rgba(66, 249, 255, 0.8)", // Aqua mouseRadius = 150, backgroundColor = "linear-gradient(to bottom, rgba(0,0,0,0.95), rgba(0,0,0,1))" }: Props) { return { canvas: document.createElement("canvas"), mount(canvas: HTMLCanvasElement) { // Set up canvas styles canvas.style.position = "fixed"; canvas.style.top = "0"; canvas.style.left = "0"; canvas.style.width = "100%"; canvas.style.height = "100%"; canvas.style.zIndex = "-1"; canvas.style.background = backgroundColor; const ctx = canvas.getContext("2d"); if (!ctx) return; // Initialize variables let particles: Array<{ x: number; y: number; vx: number; vy: number; targetX: number; targetY: number; radius: number; color: string; }> = []; const mouse = { x: 0, y: 0, radius: mouseRadius }; let animationFrame: number; // Update canvas size function updateCanvasSize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } // Generate points in a circle pattern function generatePoints() { const points: [number, number][] = []; const centerX = canvas.width / 2; const centerY = canvas.height / 2; const size = Math.min(canvas.width, canvas.height) * 0.2; const gridSize = 15; for (let x = 0; x < canvas.width; x += gridSize) { for (let y = 0; y < canvas.height; y += gridSize) { const dx = x - centerX; const dy = y - centerY; const distance = Math.sqrt(dx * dx + dy * dy); if (distance > size) { points.push([x, y]); } } } return points; } // Initialize particles function initParticles() { const points = generatePoints(); particles = points.map(([targetX, targetY]) => { const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 200; return { x: targetX + Math.cos(angle) * distance, y: targetY + Math.sin(angle) * distance, vx: (Math.random() - 0.5) * 2, vy: (Math.random() - 0.5) * 2, targetX, targetY, radius: Math.random() * 1.5 + 1, color: Math.random() < 0.5 ? primaryColor : secondaryColor }; }); } // Animation loop function animate() { if (!ctx) return; ctx.fillStyle = "rgba(0, 0, 0, 0.2)"; ctx.fillRect(0, 0, canvas.width, canvas.height); particles.forEach(particle => { // Mouse repulsion const dx = mouse.x - particle.x; const dy = mouse.y - particle.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < mouse.radius) { const force = (mouse.radius - distance) / mouse.radius; const angle = Math.atan2(dy, dx); particle.vx -= Math.cos(angle) * force * 2; particle.vy -= Math.sin(angle) * force * 2; } // Target attraction const tdx = particle.targetX - particle.x; const tdy = particle.targetY - particle.y; const targetDistance = Math.sqrt(tdx * tdx + tdy * tdy); if (targetDistance > 1) { particle.vx += (tdx / targetDistance) * 0.2; particle.vy += (tdy / targetDistance) * 0.2; } // Update position particle.x += particle.vx; particle.y += particle.vy; // Apply drag particle.vx *= 0.95; particle.vy *= 0.95; // Draw particle ctx.beginPath(); ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2); ctx.fillStyle = particle.color; ctx.fill(); }); animationFrame = requestAnimationFrame(animate); } // Event handlers function handleMouseMove(e: MouseEvent) { const rect = canvas.getBoundingClientRect(); mouse.x = e.clientX - rect.left; mouse.y = e.clientY - rect.top; } // Initialize updateCanvasSize(); initParticles(); animate(); // Add event listeners window.addEventListener("mousemove", handleMouseMove); window.addEventListener("resize", () => { updateCanvasSize(); initParticles(); }); // Cleanup function return () => { cancelAnimationFrame(animationFrame); window.removeEventListener("mousemove", handleMouseMove); window.removeEventListener("resize", updateCanvasSize); }; } }; }

Contact us.

Integrates effortlessly with all major content management systems with no technical setup required.

First name

Last name

Email

Company name

How can we help?

Contact us.

Have questions or need support? Contact our dedicated team today for personalized assistance and expert advice. We’re here to help you succeed.

First name

Last name

Email

Company name

How can we help?