118 lines
4.5 KiB
TypeScript
118 lines
4.5 KiB
TypeScript
"use client";
|
|
|
|
export function GlobeAnimation() {
|
|
return (
|
|
<div className="pointer-events-none absolute right-[-5%] top-[15%] hidden opacity-20 lg:block xl:right-[5%] xl:opacity-30">
|
|
<div className="relative h-72 w-72 xl:h-96 xl:w-96">
|
|
{/* Orbit ring 1 */}
|
|
<div className="animate-orbit absolute inset-0">
|
|
<svg viewBox="0 0 200 200" className="h-full w-full">
|
|
<ellipse
|
|
cx="100"
|
|
cy="100"
|
|
rx="95"
|
|
ry="35"
|
|
fill="none"
|
|
stroke="url(#orbitGrad1)"
|
|
strokeWidth="0.5"
|
|
strokeDasharray="4 6"
|
|
/>
|
|
<circle cx="195" cy="100" r="3" fill="#22d3ee" opacity="0.8">
|
|
<animate attributeName="opacity" values="0.4;1;0.4" dur="2s" repeatCount="indefinite" />
|
|
</circle>
|
|
<defs>
|
|
<linearGradient id="orbitGrad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
<stop offset="0%" stopColor="#8b5cf6" stopOpacity="0" />
|
|
<stop offset="50%" stopColor="#8b5cf6" stopOpacity="0.6" />
|
|
<stop offset="100%" stopColor="#22d3ee" stopOpacity="0" />
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Orbit ring 2 */}
|
|
<div className="animate-orbit-reverse absolute inset-4">
|
|
<svg viewBox="0 0 200 200" className="h-full w-full">
|
|
<ellipse
|
|
cx="100"
|
|
cy="100"
|
|
rx="80"
|
|
ry="80"
|
|
fill="none"
|
|
stroke="url(#orbitGrad2)"
|
|
strokeWidth="0.3"
|
|
strokeDasharray="2 8"
|
|
transform="rotate(-30 100 100)"
|
|
/>
|
|
<circle cx="100" cy="20" r="2.5" fill="#d946ef" opacity="0.7">
|
|
<animate attributeName="opacity" values="0.3;0.9;0.3" dur="3s" repeatCount="indefinite" />
|
|
</circle>
|
|
<defs>
|
|
<linearGradient id="orbitGrad2" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stopColor="#d946ef" stopOpacity="0.2" />
|
|
<stop offset="100%" stopColor="#34d399" stopOpacity="0.2" />
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Globe */}
|
|
<div className="absolute inset-[25%] flex items-center justify-center">
|
|
<svg viewBox="0 0 120 120" className="h-full w-full">
|
|
<defs>
|
|
<radialGradient id="globeGrad" cx="35%" cy="30%">
|
|
<stop offset="0%" stopColor="#22d3ee" stopOpacity="0.3" />
|
|
<stop offset="50%" stopColor="#8b5cf6" stopOpacity="0.15" />
|
|
<stop offset="100%" stopColor="#06060f" stopOpacity="0.05" />
|
|
</radialGradient>
|
|
<linearGradient id="globeLine" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
<stop offset="0%" stopColor="#22d3ee" stopOpacity="0.1" />
|
|
<stop offset="50%" stopColor="#8b5cf6" stopOpacity="0.3" />
|
|
<stop offset="100%" stopColor="#22d3ee" stopOpacity="0.1" />
|
|
</linearGradient>
|
|
</defs>
|
|
<circle cx="60" cy="60" r="55" fill="url(#globeGrad)" stroke="url(#globeLine)" strokeWidth="0.8" />
|
|
{/* Latitude lines */}
|
|
{[30, 45, 60, 75, 90].map((lat) => {
|
|
const ry = Math.sin((lat * Math.PI) / 180) * 55;
|
|
return (
|
|
<ellipse
|
|
key={lat}
|
|
cx="60"
|
|
cy="60"
|
|
rx="55"
|
|
ry={ry}
|
|
fill="none"
|
|
stroke="#22d3ee"
|
|
strokeWidth="0.3"
|
|
opacity="0.2"
|
|
/>
|
|
);
|
|
})}
|
|
{/* Longitude lines */}
|
|
{[0, 30, 60, 90, 120, 150].map((lon) => (
|
|
<ellipse
|
|
key={lon}
|
|
cx="60"
|
|
cy="60"
|
|
rx={Math.cos((lon * Math.PI) / 180) * 8 + 8}
|
|
ry="55"
|
|
fill="none"
|
|
stroke="#8b5cf6"
|
|
strokeWidth="0.3"
|
|
opacity="0.15"
|
|
transform={`rotate(${lon} 60 60)`}
|
|
/>
|
|
))}
|
|
{/* Glow dot */}
|
|
<circle cx="42" cy="38" r="4" fill="#22d3ee" opacity="0.6">
|
|
<animate attributeName="r" values="3;5;3" dur="4s" repeatCount="indefinite" />
|
|
<animate attributeName="opacity" values="0.3;0.8;0.3" dur="4s" repeatCount="indefinite" />
|
|
</circle>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|