feat: Implement initial cinematic portfolio UI with animated components and page structure.
This commit is contained in:
1 parent
9d779390e5
commit
2ede7e98f9
18 files changed
+2107
-147
No files matched your search
@@ -0,0 +1,156 @@
|
||||
"use client";
|
||||
|
||||
import { useRef, useMemo } from "react";
|
||||
import { Canvas, useFrame } from "@react-three/fiber";
|
||||
import { Float, MeshDistortMaterial, MeshTransmissionMaterial } from "@react-three/drei";
|
||||
import * as THREE from "three";
|
||||
|
||||
function GlassSphere({ position, scale = 1 }: { position: [number, number, number]; scale?: number }) {
|
||||
const meshRef = useRef<THREE.Mesh>(null);
|
||||
|
||||
useFrame((state) => {
|
||||
if (!meshRef.current) return;
|
||||
const t = state.clock.elapsedTime;
|
||||
meshRef.current.rotation.x = Math.sin(t * 0.3) * 0.2;
|
||||
meshRef.current.rotation.z = Math.cos(t * 0.2) * 0.1;
|
||||
});
|
||||
|
||||
return (
|
||||
<Float speed={1.5} rotationIntensity={0.3} floatIntensity={0.8}>
|
||||
<mesh ref={meshRef} position={position} scale={scale}>
|
||||
<sphereGeometry args={[1, 32, 32]} />
|
||||
<MeshDistortMaterial
|
||||
color="#ccff00"
|
||||
transparent
|
||||
opacity={0.08}
|
||||
distort={0.4}
|
||||
speed={2}
|
||||
wireframe
|
||||
/>
|
||||
</mesh>
|
||||
</Float>
|
||||
);
|
||||
}
|
||||
|
||||
function WireframeRing({ position, scale = 1 }: { position: [number, number, number]; scale?: number }) {
|
||||
const meshRef = useRef<THREE.Mesh>(null);
|
||||
|
||||
useFrame((state) => {
|
||||
if (!meshRef.current) return;
|
||||
const t = state.clock.elapsedTime;
|
||||
meshRef.current.rotation.x = t * 0.1;
|
||||
meshRef.current.rotation.y = t * 0.15;
|
||||
});
|
||||
|
||||
return (
|
||||
<Float speed={1} rotationIntensity={0.5} floatIntensity={0.4}>
|
||||
<mesh ref={meshRef} position={position} scale={scale}>
|
||||
<torusGeometry args={[1, 0.02, 16, 100]} />
|
||||
<meshStandardMaterial
|
||||
color="#ccff00"
|
||||
transparent
|
||||
opacity={0.15}
|
||||
emissive="#ccff00"
|
||||
emissiveIntensity={0.1}
|
||||
/>
|
||||
</mesh>
|
||||
</Float>
|
||||
);
|
||||
}
|
||||
|
||||
function DataStream({ count = 50 }: { count?: number }) {
|
||||
const pointsRef = useRef<THREE.Points>(null);
|
||||
|
||||
const positions = useMemo(() => {
|
||||
const pos = new Float32Array(count * 3);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const i3 = i * 3;
|
||||
// Create a spiral/helix pattern
|
||||
const angle = (i / count) * Math.PI * 8;
|
||||
const radius = 2 + Math.sin(angle * 0.5) * 0.5;
|
||||
pos[i3] = Math.cos(angle) * radius;
|
||||
pos[i3 + 1] = (i / count - 0.5) * 12;
|
||||
pos[i3 + 2] = Math.sin(angle) * radius;
|
||||
}
|
||||
return pos;
|
||||
}, [count]);
|
||||
|
||||
useFrame((state) => {
|
||||
if (!pointsRef.current) return;
|
||||
const t = state.clock.elapsedTime;
|
||||
pointsRef.current.rotation.y = t * 0.05;
|
||||
|
||||
const posAttr = pointsRef.current.geometry.getAttribute("position") as THREE.BufferAttribute;
|
||||
const arr = posAttr.array as Float32Array;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const i3 = i * 3;
|
||||
arr[i3 + 1] += 0.02;
|
||||
if (arr[i3 + 1] > 6) arr[i3 + 1] = -6;
|
||||
}
|
||||
posAttr.needsUpdate = true;
|
||||
});
|
||||
|
||||
return (
|
||||
<points ref={pointsRef}>
|
||||
<bufferGeometry>
|
||||
<bufferAttribute
|
||||
attach="attributes-position"
|
||||
args={[positions, 3]}
|
||||
count={count}
|
||||
/>
|
||||
</bufferGeometry>
|
||||
<pointsMaterial
|
||||
color="#ccff00"
|
||||
size={0.04}
|
||||
transparent
|
||||
opacity={0.4}
|
||||
sizeAttenuation
|
||||
blending={THREE.AdditiveBlending}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</points>
|
||||
);
|
||||
}
|
||||
|
||||
interface FloatingElementsProps {
|
||||
variant?: "sphere" | "ring" | "data" | "combined";
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function FloatingElements({
|
||||
variant = "combined",
|
||||
className = "",
|
||||
}: FloatingElementsProps) {
|
||||
return (
|
||||
<div className={`pointer-events-none absolute inset-0 ${className}`}>
|
||||
<Canvas
|
||||
camera={{ position: [0, 0, 6], fov: 50 }}
|
||||
dpr={[1, 1.5]}
|
||||
gl={{ antialias: false, alpha: true, powerPreference: "high-performance" }}
|
||||
style={{ background: "transparent" }}
|
||||
>
|
||||
<ambientLight intensity={0.2} />
|
||||
<pointLight position={[5, 5, 5]} intensity={0.3} color="#ccff00" />
|
||||
|
||||
{(variant === "sphere" || variant === "combined") && (
|
||||
<>
|
||||
<GlassSphere position={[3, 1, -2]} scale={0.8} />
|
||||
<GlassSphere position={[-4, -1, -3]} scale={1.2} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{(variant === "ring" || variant === "combined") && (
|
||||
<>
|
||||
<WireframeRing position={[0, 0, -2]} scale={1.5} />
|
||||
<WireframeRing position={[-3, 2, -4]} scale={0.8} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{(variant === "data" || variant === "combined") && (
|
||||
<DataStream count={60} />
|
||||
)}
|
||||
</Canvas>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user