102 lines
3.7 KiB
React
Executable File
102 lines
3.7 KiB
React
Executable File
import React, { useEffect, useState } from "react";
|
|
import { motion } from "framer-motion";
|
|
|
|
const Background = () => {
|
|
const [gridSize, setGridSize] = useState({ cols: 12, rows: 6 });
|
|
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
|
|
const [path, setPath] = useState([]);
|
|
|
|
useEffect(() => {
|
|
const updateGrid = () => {
|
|
const width = window.innerWidth;
|
|
const height = window.innerHeight;
|
|
const cols = Math.max(8, Math.floor(width / 100)); // 100px-es cellák
|
|
const rows = Math.max(5, Math.floor(height / 100)); // 100px-es cellák
|
|
setGridSize({ cols, rows });
|
|
};
|
|
|
|
const handleMouseMove = (e) => {
|
|
setMousePos({ x: e.clientX, y: e.clientY });
|
|
};
|
|
|
|
updateGrid();
|
|
window.addEventListener("resize", updateGrid);
|
|
window.addEventListener("mousemove", handleMouseMove);
|
|
|
|
return () => {
|
|
window.removeEventListener("resize", updateGrid);
|
|
window.removeEventListener("mousemove", handleMouseMove);
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
const newCol = Math.floor(Math.random() * gridSize.cols);
|
|
const newRow = Math.floor(Math.random() * gridSize.rows);
|
|
setPath((prevPath) => {
|
|
const newPath = [...prevPath, { col: newCol, row: newRow, opacity: 1 }]; // Új pont hozzáadása
|
|
if (newPath.length > 10) {
|
|
newPath.shift(); // Max 10 pont az útvonalon
|
|
}
|
|
return newPath;
|
|
});
|
|
}, 500); // Új pont hozzáadása minden 500ms-ben
|
|
|
|
// Az útvonal pontjainak fokozatos eltűnése
|
|
const fadeInterval = setInterval(() => {
|
|
setPath((prevPath) =>
|
|
prevPath.map((point) => ({
|
|
...point,
|
|
opacity: Math.max(0, point.opacity - 0.05), // Fokozatosan csökkentjük az opacity-t
|
|
})).filter((point) => point.opacity > 0) // Eltávolítjuk a teljesen eltűnt pontokat
|
|
);
|
|
}, 100); // Opacity frissítése minden 100ms-ben
|
|
|
|
return () => {
|
|
clearInterval(interval);
|
|
clearInterval(fadeInterval);
|
|
};
|
|
}, [gridSize]);
|
|
|
|
return (
|
|
<div className="relative w-full h-screen bg-background flex items-center justify-center overflow-hidden">
|
|
<div
|
|
className="absolute inset-0 grid gap-2 opacity-20"
|
|
style={{
|
|
gridTemplateColumns: `repeat(${gridSize.cols}, 1fr)`,
|
|
gridTemplateRows: `repeat(${gridSize.rows}, 1fr)`,
|
|
}}
|
|
>
|
|
{[...Array(gridSize.cols * gridSize.rows)].map((_, i) => {
|
|
const col = i % gridSize.cols;
|
|
const row = Math.floor(i / gridSize.cols);
|
|
const cellX = (col + 0.5) * (window.innerWidth / gridSize.cols);
|
|
const cellY = (row + 0.5) * (window.innerHeight / gridSize.rows);
|
|
|
|
const dx = cellX - mousePos.x;
|
|
const dy = cellY - mousePos.y;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
const distanceFactor = Math.max(0, 1 - distance / 300); // Egér hatótávolsága
|
|
|
|
// Az útvonalban lévő pontok opacitása
|
|
const pathPoint = path.find((p) => p.col === col && p.row === row);
|
|
const pathOpacity = pathPoint ? pathPoint.opacity : 0;
|
|
|
|
return (
|
|
<motion.div
|
|
key={i}
|
|
className="w-full h-full bg-white rounded-lg"
|
|
animate={{
|
|
opacity: 0.05 + distanceFactor * 0.2 + pathOpacity * 0.5, // Kombinált opacitás
|
|
scale: 1 + distanceFactor * 0.05 + pathOpacity * 0.1, // Kombinált skálázás
|
|
}}
|
|
transition={{ duration: 0.5, ease: "easeOut" }} // Lassú és sima átmenet
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Background; |