feat: initialize reactjs project using vite
This commit is contained in:
20
src/components/effects/Scene3D.module.css
Normal file
20
src/components/effects/Scene3D.module.css
Normal file
@@ -0,0 +1,20 @@
|
||||
.container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.container canvas {
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
/* Fade out on smaller screens */
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
96
src/components/effects/Scene3D.tsx
Normal file
96
src/components/effects/Scene3D.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { useRef, useMemo } from 'react';
|
||||
import { Canvas, useFrame } from '@react-three/fiber';
|
||||
import { Float, MeshDistortMaterial } from '@react-three/drei';
|
||||
import * as THREE from 'three';
|
||||
import styles from './Scene3D.module.css';
|
||||
|
||||
function FloatingShape() {
|
||||
const meshRef = useRef<THREE.Mesh>(null);
|
||||
|
||||
useFrame((state) => {
|
||||
if (meshRef.current) {
|
||||
meshRef.current.rotation.x = state.clock.elapsedTime * 0.1;
|
||||
meshRef.current.rotation.y = state.clock.elapsedTime * 0.15;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Float
|
||||
speed={2}
|
||||
rotationIntensity={0.5}
|
||||
floatIntensity={1}
|
||||
>
|
||||
<mesh ref={meshRef} scale={2.5}>
|
||||
<icosahedronGeometry args={[1, 1]} />
|
||||
<MeshDistortMaterial
|
||||
color="#7FD998"
|
||||
emissive="#004D2A"
|
||||
emissiveIntensity={0.3}
|
||||
roughness={0.4}
|
||||
metalness={0.8}
|
||||
distort={0.3}
|
||||
speed={2}
|
||||
/>
|
||||
</mesh>
|
||||
</Float>
|
||||
);
|
||||
}
|
||||
|
||||
function ParticleField() {
|
||||
const count = 100;
|
||||
|
||||
const positions = useMemo(() => {
|
||||
const pos = new Float32Array(count * 3);
|
||||
for (let i = 0; i < count; i++) {
|
||||
pos[i * 3] = (Math.random() - 0.5) * 20;
|
||||
pos[i * 3 + 1] = (Math.random() - 0.5) * 20;
|
||||
pos[i * 3 + 2] = (Math.random() - 0.5) * 20;
|
||||
}
|
||||
return pos;
|
||||
}, []);
|
||||
|
||||
const pointsRef = useRef<THREE.Points>(null);
|
||||
|
||||
useFrame((state) => {
|
||||
if (pointsRef.current) {
|
||||
pointsRef.current.rotation.y = state.clock.elapsedTime * 0.02;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<points ref={pointsRef}>
|
||||
<bufferGeometry>
|
||||
<bufferAttribute
|
||||
attach="attributes-position"
|
||||
args={[positions, 3]}
|
||||
/>
|
||||
</bufferGeometry>
|
||||
<pointsMaterial
|
||||
size={0.05}
|
||||
color="#7FD998"
|
||||
transparent
|
||||
opacity={0.6}
|
||||
sizeAttenuation
|
||||
/>
|
||||
</points>
|
||||
);
|
||||
}
|
||||
|
||||
export function Scene3D() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Canvas
|
||||
camera={{ position: [0, 0, 8], fov: 45 }}
|
||||
dpr={[1, 2]}
|
||||
gl={{ antialias: true, alpha: true }}
|
||||
>
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[10, 10, 5]} intensity={1} />
|
||||
<pointLight position={[-10, -10, -5]} intensity={0.5} color="#7FD998" />
|
||||
|
||||
<FloatingShape />
|
||||
<ParticleField />
|
||||
</Canvas>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1
src/components/effects/index.ts
Normal file
1
src/components/effects/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { Scene3D } from './Scene3D';
|
||||
Reference in New Issue
Block a user