2025-12-11 11:30:18 +08:00

172 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useRef, useMemo } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Float, Stars } from '@react-three/drei';
import * as THREE from 'three';
// ------------------- Three.js Components -------------------
const GeometryArt = () => {
const meshRef = useRef<THREE.Mesh>(null);
useFrame((state) => {
if (meshRef.current) {
meshRef.current.rotation.x = state.clock.getElapsedTime() * 0.1;
meshRef.current.rotation.y = state.clock.getElapsedTime() * 0.15;
}
});
return (
<Float speed={1.5} rotationIntensity={0.5} floatIntensity={0.5}>
<mesh ref={meshRef} position={[2, 0, 0]} scale={1.8}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color="#C5A059"
wireframe
transparent
opacity={0.3}
roughness={0}
metalness={1}
/>
</mesh>
<mesh position={[2, 0, 0]} scale={0.5}>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial
color="#C5A059"
emissive="#C5A059"
emissiveIntensity={0.5}
roughness={0.2}
metalness={1}
/>
</mesh>
</Float>
);
};
const ConnectingLines = () => {
// Create random connections mimicking a network
const count = 40;
const lines = useMemo(() => {
const points: [number, number, number][] = [];
// Use a fixed seed for consistent but pseudo-random positioning
const seed = 12345;
const seededRandom = (i: number) => {
const x = Math.sin(seed + i * 12.9898) * 43758.5453123;
return x - Math.floor(x);
};
for (let i = 0; i < count; i++) {
points.push([
(seededRandom(i * 3) - 0.5) * 10,
(seededRandom(i * 3 + 1) - 0.5) * 6,
(seededRandom(i * 3 + 2) - 0.5) * 5
]);
}
return points;
}, []);
const ref = useRef<THREE.Group>(null);
useFrame((state) => {
if (ref.current) {
ref.current.rotation.y = -state.clock.getElapsedTime() * 0.05;
}
});
return (
<group ref={ref}>
{lines.map((pos, i) => (
<mesh key={i} position={new THREE.Vector3(...pos)}>
<sphereGeometry args={[0.02, 8, 8]} />
<meshBasicMaterial color="#ffffff" opacity={0.4} transparent />
</mesh>
))}
</group>
)
}
const Scene = () => {
return (
<>
<ambientLight intensity={0.2} />
<pointLight position={[10, 10, 10]} intensity={1.5} color="#C5A059" />
<pointLight position={[-10, -10, -10]} intensity={0.5} color="#4c4c4c" />
<spotLight position={[0, 5, 0]} angle={0.3} penumbra={1} intensity={2} color="white" />
<GeometryArt />
<ConnectingLines />
<Stars radius={100} depth={50} count={5000} factor={4} saturation={0} fade speed={1} />
</>
);
};
// ------------------- Main Component -------------------
const Hero: React.FC = () => {
return (
<section id="hero" className="relative w-full h-screen bg-feie-dark overflow-hidden">
{/* 3D Canvas Layer */}
<div className="absolute inset-0 z-0">
<Canvas camera={{ position: [0, 0, 6], fov: 45 }}>
<Scene />
</Canvas>
</div>
{/* Content Overlay */}
<div className="absolute inset-0 z-10 flex items-center">
<div className="container mx-auto px-6 grid grid-cols-1 md:grid-cols-2">
<div className="text-left space-y-6">
<div className="inline-block px-3 py-1 border border-feie-gold/50 rounded-full">
<span className="text-feie-gold text-xs font-serif tracking-widest uppercase">
Est. Nanjing Technology Leader
</span>
</div>
<h1 className="text-5xl md:text-7xl font-serif text-feie-white leading-tight">
<br />
<span className="text-feie-gold italic"></span>
</h1>
<p className="text-feie-white/70 text-lg md:text-xl font-light max-w-md leading-relaxed">
</p>
<div className="pt-8 flex gap-4">
<a
href="#services"
className="px-8 py-3 bg-feie-gold text-feie-white font-serif hover:bg-yellow-600 transition-colors duration-300 rounded-sm"
>
</a>
<a
href="#contact"
className="px-8 py-3 border border-feie-white text-feie-white font-serif hover:bg-feie-white hover:text-feie-dark transition-colors duration-300 rounded-sm"
>
</a>
</div>
</div>
{/* Right side is empty to allow the 3D visual to shine */}
<div className="hidden md:block"></div>
</div>
</div>
{/* Scroll indicator */}
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-10 animate-bounce">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="opacity-50"
>
<path d="M12 5v14M19 12l-7 7-7-7"/>
</svg>
</div>
</section>
);
};
export default Hero;