Updated the network animation to enhance its elegance and visual appeal.
[skip gpt_engineer]
Этот коммит содержится в:
gpt-engineer-app[bot] 2024-12-15 12:21:01 +00:00
родитель 232ec7e58e
Коммит 23e32c1e18

Просмотреть файл

@ -1,90 +1,112 @@
import React from 'react'; import React, { useEffect, useRef } from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
interface Node { interface Node {
id: number; id: number;
baseX: number; x: number;
baseY: number; y: number;
size: number;
delay: number;
} }
export const NetworkAnimation = ({ className = '' }: { className?: string }) => { export const NetworkAnimation = ({ className = '' }: { className?: string }) => {
const nodes: Node[] = Array.from({ length: 6 }, (_, i) => { const containerRef = useRef<HTMLDivElement>(null);
const row = Math.floor(i / 2);
const col = i % 2; // Generate nodes with different sizes and positions
return { const nodes: Node[] = Array.from({ length: 12 }, (_, i) => ({
id: i, id: i,
baseX: 30 + col * 40, x: 20 + Math.random() * 60, // Random position between 20-80%
baseY: 25 + row * 25, y: 20 + Math.random() * 60,
}; size: 2 + Math.random() * 2, // Random size between 2-4
}); delay: i * 0.1 // Staggered animation delay
}));
// Create pairs of nodes for connections
const connections = nodes.flatMap((node, i) =>
nodes.slice(i + 1).map(otherNode => ({
id: `${node.id}-${otherNode.id}`,
from: node,
to: otherNode,
opacity: Math.random() * 0.3 + 0.1 // Random opacity between 0.1-0.4
}))
);
return ( return (
<div className={`relative w-full h-40 overflow-hidden bg-black/20 rounded-lg ${className}`}> <div
<svg className="absolute inset-0 w-full h-full pointer-events-none"> ref={containerRef}
{nodes.map((node1) => className={`relative w-full h-40 overflow-hidden bg-black/20 rounded-lg ${className}`}
nodes >
.filter((node2) => node2.id !== node1.id) <svg className="absolute inset-0 w-full h-full">
.map((node2) => ( {/* Render connections between nodes */}
{connections.map(({ id, from, to, opacity }) => (
<motion.line <motion.line
key={`${node1.id}-${node2.id}`} key={id}
x1={`${node1.baseX}%`} x1={`${from.x}%`}
y1={`${node1.baseY}%`} y1={`${from.y}%`}
x2={`${node2.baseX}%`} x2={`${to.x}%`}
y2={`${node2.baseY}%`} y2={`${to.y}%`}
stroke="rgba(255, 215, 0, 0.15)" stroke="rgba(255, 215, 0, 0.2)"
strokeWidth="1" strokeWidth="0.5"
initial={{ opacity: 0 }} initial={{ opacity: 0, pathLength: 0 }}
animate={{ animate={{
opacity: [0, 0.5, 0], opacity: [0, opacity, opacity/2],
x1: [`${node1.baseX}%`, `${node1.baseX + (Math.random() > 0.5 ? 10 : -10)}%`], pathLength: [0, 1, 1]
y1: [`${node1.baseY}%`, `${node1.baseY + (Math.random() > 0.5 ? 10 : -10)}%`],
x2: [`${node2.baseX}%`, `${node2.baseX + (Math.random() > 0.5 ? 10 : -10)}%`],
y2: [`${node2.baseY}%`, `${node2.baseY + (Math.random() > 0.5 ? 10 : -10)}%`],
}} }}
transition={{ transition={{
duration: 4, duration: 3,
repeat: Infinity,
repeatType: "mirror",
ease: "easeInOut"
}}
/>
))
)}
</svg>
{nodes.map((node) => (
<motion.div
key={node.id}
className="absolute w-3 h-3"
style={{
left: '-6px',
top: '-6px',
}}
animate={{
x: [
`${node.baseX}%`,
`${node.baseX + (Math.random() > 0.5 ? 10 : -10)}%`,
`${node.baseX}%`,
],
y: [
`${node.baseY}%`,
`${node.baseY + (Math.random() > 0.5 ? 10 : -10)}%`,
`${node.baseY}%`,
],
}}
transition={{
duration: 6,
repeat: Infinity, repeat: Infinity,
repeatType: "reverse", repeatType: "reverse",
ease: "easeInOut", ease: "easeInOut",
delay: node.id * 0.2, delay: from.delay
}}
/>
))}
</svg>
{/* Render nodes */}
{nodes.map((node) => (
<motion.div
key={node.id}
className="absolute"
style={{
left: `${node.x}%`,
top: `${node.y}%`,
width: `${node.size}px`,
height: `${node.size}px`,
}}
initial={{ scale: 0, opacity: 0 }}
animate={{
scale: [0, 1, 1.2, 1],
opacity: [0, 1, 0.8, 1],
x: [
-10,
10,
-5,
5,
0
],
y: [
-5,
5,
-10,
10,
0
]
}}
transition={{
duration: 8,
repeat: Infinity,
repeatType: "reverse",
ease: "easeInOut",
delay: node.delay,
}} }}
> >
{/* Core node */}
<motion.div <motion.div
className="absolute w-full h-full rounded-full bg-yellow-500" className="absolute w-full h-full rounded-full bg-yellow-500"
animate={{ animate={{
scale: [1, 1.2, 1], scale: [1, 1.2, 1],
opacity: [0.7, 1, 0.7], opacity: [0.8, 1, 0.8],
}} }}
transition={{ transition={{
duration: 2, duration: 2,
@ -93,6 +115,7 @@ export const NetworkAnimation = ({ className = '' }: { className?: string }) =>
}} }}
/> />
{/* Outer glow */}
<motion.div <motion.div
className="absolute w-full h-full rounded-full bg-yellow-500/30" className="absolute w-full h-full rounded-full bg-yellow-500/30"
animate={{ animate={{
@ -103,9 +126,29 @@ export const NetworkAnimation = ({ className = '' }: { className?: string }) =>
duration: 3, duration: 3,
repeat: Infinity, repeat: Infinity,
ease: "easeInOut", ease: "easeInOut",
delay: node.id * 0.1, delay: node.delay * 0.5,
}} }}
/> />
{/* Particle effects */}
{Array.from({ length: 3 }).map((_, i) => (
<motion.div
key={i}
className="absolute w-1 h-1 rounded-full bg-yellow-500/20"
animate={{
x: [0, (i - 1) * 10],
y: [0, (i - 1) * 10],
scale: [0, 1, 0],
opacity: [0, 0.5, 0],
}}
transition={{
duration: 2,
repeat: Infinity,
delay: i * 0.3 + node.delay,
ease: "easeOut",
}}
/>
))}
</motion.div> </motion.div>
))} ))}
</div> </div>