Skip to content

Instantly share code, notes, and snippets.

@floydnoel
Created February 6, 2025 23:28
Show Gist options
  • Save floydnoel/1e38d35d74177a908d2dbef6a2ee30c1 to your computer and use it in GitHub Desktop.
Save floydnoel/1e38d35d74177a908d2dbef6a2ee30c1 to your computer and use it in GitHub Desktop.
A simple particle background as a React hook
// 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