Created
February 6, 2025 23:28
-
-
Save floydnoel/1e38d35d74177a908d2dbef6a2ee30c1 to your computer and use it in GitHub Desktop.
A simple particle background as a React hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// useBackgroundAnimation.js | |
import { useEffect, useRef } from 'react'; | |
export function useBackgroundAnimation() { | |
const canvasRef = useRef(null); | |
const containerRef = useRef(null); | |
useEffect(() => { | |
const canvas = canvasRef.current; | |
const container = containerRef.current; | |
const ctx = canvas.getContext('2d'); | |
const resizeCanvas = () => { | |
const rect = container.getBoundingClientRect(); | |
canvas.width = rect.width; | |
canvas.height = rect.height; | |
}; | |
resizeCanvas(); | |
window.addEventListener('resize', resizeCanvas); | |
// Particle setup | |
const particles = Array.from({ length: 48 }, () => ({ | |
x: Math.random() * canvas.width, | |
y: Math.random() * canvas.height, | |
size: 1.5, | |
dx: (Math.random() - 0.5) * 1, | |
dy: (Math.random() - 0.5) * 1, | |
})); | |
const maxDistance = 150; | |
const drawConnections = (particleColor) => { | |
particles.forEach((p1, i) => { | |
particles.slice(i + 1).forEach((p2) => { | |
const dx = p1.x - p2.x; | |
const dy = p1.y - p2.y; | |
const distance = Math.sqrt(dx * dx + dy * dy); | |
if (distance < maxDistance) { | |
const opacity = 1 - distance / maxDistance; | |
ctx.beginPath(); | |
ctx.strokeStyle = particleColor; | |
ctx.lineWidth = opacity; | |
ctx.moveTo(p1.x, p1.y); | |
ctx.lineTo(p2.x, p2.y); | |
ctx.stroke(); | |
} | |
}); | |
}); | |
}; | |
const animate = () => { | |
// Create temporary element to get computed bg color | |
const temp = document.createElement('div'); | |
temp.className = 'bg-base-100'; | |
document.body.appendChild(temp); | |
const bgColor = window.getComputedStyle(temp).backgroundColor; | |
document.body.removeChild(temp); | |
ctx.fillStyle = bgColor; | |
ctx.fillRect(0, 0, canvas.width, canvas.height); | |
particles.forEach((p) => { | |
p.x += p.dx; | |
p.y += p.dy; | |
if (p.x < 0 || p.x > canvas.width) p.dx *= -1; | |
if (p.y < 0 || p.y > canvas.height) p.dy *= -1; | |
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)'; | |
ctx.beginPath(); | |
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); | |
ctx.fill(); | |
}); | |
drawConnections('rgba(255, 255, 255, 0.2)'); | |
requestAnimationFrame(animate); | |
}; | |
animate(); | |
return () => { | |
window.removeEventListener('resize', resizeCanvas); | |
}; | |
}, []); | |
return { canvasRef, containerRef }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment