feat: add loading effect

This commit is contained in:
neru
2026-01-02 04:52:30 -03:00
parent a2e4637c8d
commit 1e5b9c8884
2 changed files with 92 additions and 48 deletions
+19
View File
@@ -2,3 +2,22 @@
width: 100vw !important; width: 100vw !important;
height: 100vh !important; height: 100vh !important;
} }
.loader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: black;
z-index: 4444;
transition: opacity 1.0s ease-in-out;
pointer-events: none;
opacity: 1;
display: block;
}
.loader.hidden {
opacity: 0;
}
+73 -48
View File
@@ -3,7 +3,8 @@
import { import {
Environment, Environment,
OrbitControls, OrbitControls,
PerspectiveCamera PerspectiveCamera,
useProgress
} from '@react-three/drei'; } from '@react-three/drei';
import { Canvas, useLoader, useFrame } from '@react-three/fiber'; import { Canvas, useLoader, useFrame } from '@react-three/fiber';
import { import {
@@ -24,7 +25,8 @@ import {
DoubleSide, DoubleSide,
TextureLoader, TextureLoader,
Color, Color,
MeshStandardMaterial MeshStandardMaterial,
FogExp2
} from 'three'; } from 'three';
import './page.css'; import './page.css';
@@ -613,57 +615,80 @@ const SealCube = forwardRef<Mesh>((props, ref) => {
}); });
SealCube.displayName = 'SealCube'; SealCube.displayName = 'SealCube';
function Loader() {
const { progress, active } = useProgress();
const [visible, setVisible] = useState(true);
useLayoutEffect(() => {
if (!active && progress === 100) {
const timeout = setTimeout(() => setVisible(false), 500);
return () => clearTimeout(timeout);
}
}, [progress, active]);
return (
<div
className={`loader ${!visible ? 'loader hidden' : ''}`}
/>
);
}
export default function Home() { export default function Home() {
const [sealMesh, setSealMesh] = useState<Mesh | null>(null); const [sealMesh, setSealMesh] = useState<Mesh | null>(null);
return ( return (
<Canvas <>
shadows <Loader />
camera={{ position: [0, 5, 15], fov: 50, far: 100 }} <Canvas
gl={{ antialias: true }} shadows
className='canvas' camera={{ position: [0, 5, 15], fov: 50, far: 100 }}
> gl={{ antialias: true }}
<EffectComposer> className='canvas'
<DepthOfField target={[0, 3, 0]} focalLength={10} bokehScale={5} /> >
<Vignette /> <EffectComposer>
<Noise opacity={0.05} /> <DepthOfField target={[0, 3, 0]} focalLength={10} bokehScale={5} />
<Bloom <Vignette />
intensity={2} <Noise opacity={0.05} />
luminanceThreshold={0.5} <Bloom
luminanceSmoothing={0.1} intensity={2}
luminanceThreshold={0.5}
luminanceSmoothing={0.1}
/>
<SMAA />
</EffectComposer>
<Environment files={'hdr/sky.hdr'} environmentIntensity={1} background />
<fogExp2 attach='fog' args={[0x9A9A9A, 0.01]} />
<Terrain
chunks={16}
chunkSize={10.0}
resolution={8.0}
scale={1}
hillScale={0.1}
hillHeight={6.0}
detailScale={1.0}
detailHeight={0.2}
wireframe={false}
grassCount={6000}
grassSize={0.6}
grassLOD={60}
/>
<SealCube
ref={(mesh) => {
if (mesh && !sealMesh) setSealMesh(mesh);
}}
/> />
<SMAA />
</EffectComposer>
<Environment files={'hdr/sky.hdr'} environmentIntensity={1} background /> <OrbitControls
target={[0, 3, 0]}
<Terrain enablePan={false}
chunks={16} makeDefault
chunkSize={10.0} minDistance={2}
resolution={8.0} maxDistance={10}
scale={1} />
hillScale={0.1} </Canvas>
hillHeight={6.0} </>
detailScale={1.0}
detailHeight={0.2}
wireframe={false}
grassCount={6000}
grassSize={0.6}
grassLOD={60}
/>
<SealCube
ref={(mesh) => {
if (mesh && !sealMesh) setSealMesh(mesh);
}}
/>
<OrbitControls
target={[0, 3, 0]}
enablePan={false}
makeDefault
minDistance={2}
maxDistance={10}
/>
</Canvas>
); );
} }