PaperStack / components /Background.tsx
Akhil-Theerthala's picture
Upload 14 files
6fe3275 verified
raw
history blame
3.21 kB
import React, { useEffect, useRef } from 'react';
const Background: React.FC<{ theme: 'light' | 'dark' }> = ({ theme }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
let animationFrameId: number;
let time = 0;
const resize = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
window.addEventListener('resize', resize);
resize();
const points: { x: number; y: number; z: number }[] = [];
const numPoints = 50; // Reduced count slightly
const size = 300;
// Create a cube of dots
for (let i = 0; i < numPoints; i++) {
points.push({
x: (Math.random() - 0.5) * size,
y: (Math.random() - 0.5) * size,
z: (Math.random() - 0.5) * size,
});
}
const draw = () => {
// Varied, slower speed
time += 0.001 + Math.sin(Date.now() * 0.0005) * 0.0005;
ctx.clearRect(0, 0, canvas.width, canvas.height);
const cx = canvas.width / 2;
const cy = canvas.height / 2;
// Much lower opacity for better contrast with content
const color = theme === 'dark' ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.05)';
const connectionColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.02)' : 'rgba(0, 0, 0, 0.02)';
ctx.fillStyle = color;
ctx.strokeStyle = connectionColor;
// Rotate points
const rotatedPoints = points.map(p => {
// Rotate Y
let x = p.x * Math.cos(time) - p.z * Math.sin(time);
let z = p.x * Math.sin(time) + p.z * Math.cos(time);
// Rotate X
let y = p.y * Math.cos(time * 0.5) - z * Math.sin(time * 0.5);
z = p.y * Math.sin(time * 0.5) + z * Math.cos(time * 0.5);
// Perspective projection
const scale = 800 / (800 + z);
return {
x: cx + x * scale,
y: cy + y * scale,
scale
};
});
// Draw connections
ctx.beginPath();
for (let i = 0; i < rotatedPoints.length; i++) {
for (let j = i + 1; j < rotatedPoints.length; j++) {
const dx = rotatedPoints[i].x - rotatedPoints[j].x;
const dy = rotatedPoints[i].y - rotatedPoints[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 120) {
ctx.moveTo(rotatedPoints[i].x, rotatedPoints[i].y);
ctx.lineTo(rotatedPoints[j].x, rotatedPoints[j].y);
}
}
}
ctx.stroke();
// Draw points
rotatedPoints.forEach(p => {
ctx.beginPath();
ctx.arc(p.x, p.y, 2 * p.scale, 0, Math.PI * 2);
ctx.fill();
});
animationFrameId = requestAnimationFrame(draw);
};
draw();
return () => {
window.removeEventListener('resize', resize);
cancelAnimationFrame(animationFrameId);
};
}, [theme]);
return (
<canvas
ref={canvasRef}
className="fixed top-0 left-0 w-full h-full -z-10 pointer-events-none transition-opacity duration-1000 opacity-20"
/>
);
};
export default Background;