2025-08-20 13:31:55 +08:00

134 lines
4.0 KiB
TypeScript

"use client";
import { Canvas, useFrame } from "@react-three/fiber";
import { Float, OrbitControls, Points, PointMaterial } from "@react-three/drei";
import { useMemo, useRef } from "react";
import * as THREE from "three";
function StarsBackground() {
const ref = useRef<THREE.Points | null>(null);
const positions = useMemo(() => {
const p = new Float32Array(6000);
for (let i = 0; i < 6000; i += 3) {
p[i] = (Math.random() - 0.5) * 60;
p[i + 1] = (Math.random() - 0.5) * 60;
p[i + 2] = (Math.random() - 0.5) * 60;
}
return p;
}, []);
useFrame((_, delta) => {
if (ref.current) ref.current.rotation.y += delta * 0.015;
});
return (
<group rotation={[0, 0, Math.PI / 8]}>
<Points ref={ref} positions={positions} stride={3} frustumCulled>
<PointMaterial
transparent
color="#60a5fa"
size={0.06}
sizeAttenuation
depthWrite={false}
/>
</Points>
</group>
);
}
function DataCore() {
const coreRef = useRef<THREE.Group | null>(null);
const orbitRef = useRef<THREE.Group | null>(null);
const nodesRef = useRef<THREE.Group | null>(null);
// Pre-generate node positions on a tilted orbit
const nodes = useMemo(() => {
const arr: { position: [number, number, number] }[] = [];
const radius = 2.4;
for (let i = 0; i < 14; i++) {
const a = (i / 14) * Math.PI * 2;
const tilt = 0.45; // slight vertical variation
arr.push({ position: [Math.cos(a) * radius, Math.sin(a) * tilt, Math.sin(a) * radius] });
}
return arr;
}, []);
useFrame((_, delta) => {
if (coreRef.current) coreRef.current.rotation.y += delta * 0.15;
if (orbitRef.current) orbitRef.current.rotation.y -= delta * 0.1;
if (nodesRef.current) nodesRef.current.rotation.y += delta * 0.22;
});
return (
<group position={[0, 0, -4]}>
{/* Central sphere */}
<mesh ref={coreRef}>
<icosahedronGeometry args={[1.05, 2]} />
<meshStandardMaterial
color="#3b82f6"
emissive="#1e40af"
emissiveIntensity={0.85}
metalness={0.35}
roughness={0.3}
/>
</mesh>
{/* Subtle inner glow shell */}
<mesh>
<sphereGeometry args={[1.35, 32, 32]} />
<meshBasicMaterial color="#60a5fa" transparent opacity={0.08} />
</mesh>
{/* Rotating analytic rings */}
<group ref={orbitRef}>
{[
{ r: 1.75, rot: [Math.PI / 2, 0, 0] },
{ r: 2.0, rot: [0.35, 0.6, 0] },
{ r: 2.25, rot: [0.9, 0.2, 0.4] },
].map((cfg, i) => (
<mesh key={i} rotation={cfg.rot as [number, number, number]}>
<torusGeometry args={[cfg.r, 0.015, 8, 160]} />
<meshStandardMaterial
color="#64748b"
emissive="#1e293b"
emissiveIntensity={0.25}
metalness={0.2}
roughness={0.4}
/>
</mesh>
))}
</group>
{/* Orbiting nodes */}
<group ref={nodesRef}>
{nodes.map((n, idx) => (
<mesh key={idx} position={n.position}>
<sphereGeometry args={[0.09, 16, 16]} />
<meshStandardMaterial
color="#93c5fd"
emissive="#1d4ed8"
emissiveIntensity={0.6}
metalness={0.3}
roughness={0.35}
/>
</mesh>
))}
</group>
</group>
);
}
export default function Scene() {
return (
<div className="fixed inset-0 -z-10">
<Canvas camera={{ position: [0, 0, 16], fov: 65 }}>
<StarsBackground />
<ambientLight intensity={0.5} />
<pointLight position={[8, 6, 8]} intensity={1.4} />
<pointLight position={[-6, -4, -6]} intensity={0.6} color="#1e3a8a" />
<OrbitControls enableZoom={false} enablePan={false} autoRotate autoRotateSpeed={0.4} />
<Float speed={1.2} floatIntensity={1.4} rotationIntensity={0.6}>
<DataCore />
</Float>
</Canvas>
</div>
);
}