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 */}
<motion.line {connections.map(({ id, from, to, opacity }) => (
key={`${node1.id}-${node2.id}`} <motion.line
x1={`${node1.baseX}%`} key={id}
y1={`${node1.baseY}%`} x1={`${from.x}%`}
x2={`${node2.baseX}%`} y1={`${from.y}%`}
y2={`${node2.baseY}%`} x2={`${to.x}%`}
stroke="rgba(255, 215, 0, 0.15)" y2={`${to.y}%`}
strokeWidth="1" stroke="rgba(255, 215, 0, 0.2)"
initial={{ opacity: 0 }} strokeWidth="0.5"
animate={{ initial={{ opacity: 0, pathLength: 0 }}
opacity: [0, 0.5, 0], animate={{
x1: [`${node1.baseX}%`, `${node1.baseX + (Math.random() > 0.5 ? 10 : -10)}%`], opacity: [0, opacity, opacity/2],
y1: [`${node1.baseY}%`, `${node1.baseY + (Math.random() > 0.5 ? 10 : -10)}%`], pathLength: [0, 1, 1]
x2: [`${node2.baseX}%`, `${node2.baseX + (Math.random() > 0.5 ? 10 : -10)}%`], }}
y2: [`${node2.baseY}%`, `${node2.baseY + (Math.random() > 0.5 ? 10 : -10)}%`], transition={{
}} duration: 3,
transition={{ repeat: Infinity,
duration: 4, repeatType: "reverse",
repeat: Infinity, ease: "easeInOut",
repeatType: "mirror", delay: from.delay
ease: "easeInOut" }}
}} />
/> ))}
))
)}
</svg> </svg>
{/* Render nodes */}
{nodes.map((node) => ( {nodes.map((node) => (
<motion.div <motion.div
key={node.id} key={node.id}
className="absolute w-3 h-3" className="absolute"
style={{ style={{
left: '-6px', left: `${node.x}%`,
top: '-6px', top: `${node.y}%`,
width: `${node.size}px`,
height: `${node.size}px`,
}} }}
initial={{ scale: 0, opacity: 0 }}
animate={{ animate={{
scale: [0, 1, 1.2, 1],
opacity: [0, 1, 0.8, 1],
x: [ x: [
`${node.baseX}%`, -10,
`${node.baseX + (Math.random() > 0.5 ? 10 : -10)}%`, 10,
`${node.baseX}%`, -5,
5,
0
], ],
y: [ y: [
`${node.baseY}%`, -5,
`${node.baseY + (Math.random() > 0.5 ? 10 : -10)}%`, 5,
`${node.baseY}%`, -10,
], 10,
0
]
}} }}
transition={{ transition={{
duration: 6, duration: 8,
repeat: Infinity, repeat: Infinity,
repeatType: "reverse", repeatType: "reverse",
ease: "easeInOut", ease: "easeInOut",
delay: node.id * 0.2, 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>