InnerVoice / frontend /components /ThreeBackground.tsx
E5K7's picture
InnerVoice Production Upgrade: Multi-channel chat, premium UI components, Whisper-small accuracy upgrade, and full-screen layout polishing
b5e8a53
"use client";
import { Canvas, useFrame } from "@react-three/fiber";
import { useRef, useMemo } from "react";
import * as THREE from "three";
function ParticleField() {
const points = useRef<THREE.Points>(null);
const particlesCount = 1000;
const positions = useMemo(() => {
const pos = new Float32Array(particlesCount * 3);
for (let i = 0; i < particlesCount; i++) {
pos[i * 3] = (Math.random() - 0.5) * 50;
pos[i * 3 + 1] = (Math.random() - 0.5) * 50;
pos[i * 3 + 2] = (Math.random() - 0.5) * 50;
}
return pos;
}, []);
useFrame((state) => {
if (points.current) {
points.current.rotation.y = state.clock.elapsedTime * 0.05;
points.current.rotation.x = state.clock.elapsedTime * 0.03;
}
});
return (
<points ref={points}>
<bufferGeometry>
<bufferAttribute
attach="attributes-position"
count={particlesCount}
array={positions}
itemSize={3}
/>
</bufferGeometry>
<pointsMaterial
size={0.05}
color="#0070f3"
transparent
opacity={0.6}
sizeAttenuation
/>
</points>
);
}
function WaveGrid() {
const mesh = useRef<THREE.Mesh>(null);
useFrame((state) => {
if (mesh.current) {
const time = state.clock.elapsedTime;
const geometry = mesh.current.geometry as THREE.PlaneGeometry;
const positions = geometry.attributes.position;
for (let i = 0; i < positions.count; i++) {
const x = positions.getX(i);
const y = positions.getY(i);
const wave = Math.sin(x * 0.5 + time) * Math.cos(y * 0.5 + time) * 0.3;
positions.setZ(i, wave);
}
positions.needsUpdate = true;
}
});
return (
<mesh ref={mesh} rotation={[-Math.PI / 3, 0, 0]} position={[0, -5, 0]}>
<planeGeometry args={[20, 20, 32, 32]} />
<meshBasicMaterial
color="#0070f3"
wireframe
transparent
opacity={0.1}
/>
</mesh>
);
}
export default function ThreeBackground() {
return (
<div className="fixed inset-0 -z-10">
<Canvas camera={{ position: [0, 0, 10], fov: 75 }}>
<ambientLight intensity={0.5} />
<ParticleField />
<WaveGrid />
</Canvas>
</div>
);
}