feat(web): show asset loading progress in the 3D scene

This commit is contained in:
2026-08-08 18:41:41 +08:00
parent c04d99fe38
commit c3c7fe2445
+24 -2
View File
@@ -1,6 +1,6 @@
import { Suspense, type ReactNode } from 'react';
import { Canvas } from '@react-three/fiber';
import { Bounds, ContactShadows, OrbitControls } from '@react-three/drei';
import { Bounds, ContactShadows, OrbitControls, useProgress } from '@react-three/drei';
import { Bloom, EffectComposer, Vignette } from '@react-three/postprocessing';
/**
@@ -15,7 +15,8 @@ import { Bloom, EffectComposer, Vignette } from '@react-three/postprocessing';
*/
export default function Scene({ children }: { children: ReactNode }) {
return (
<div className="h-80 w-full overflow-hidden rounded-lg bg-linear-to-b from-zinc-900 to-zinc-950">
<div className="relative h-80 w-full overflow-hidden rounded-lg bg-linear-to-b from-zinc-900 to-zinc-950">
<LoadingOverlay />
<Canvas
camera={{ position: [2.2, 1.8, 2.6], fov: 40 }}
dpr={[1, 2]}
@@ -54,3 +55,24 @@ export default function Scene({ children }: { children: ReactNode }) {
</div>
);
}
/**
* A loading overlay shown while assets (textures, models, traces) are being
* fetched. Reads drei's global progress store, which tracks every loader in
* the scene, so it works outside the Canvas. Hidden once loading completes.
*/
function LoadingOverlay() {
const { active, progress, item, loaded, total } = useProgress();
if (!active) return null;
return (
<div className="absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 bg-zinc-950/70 text-sm text-zinc-300">
<div className="flex items-center gap-2">
<span className="h-4 w-4 animate-spin rounded-full border-2 border-zinc-600 border-t-zinc-200" />
<span>Loading assets {Math.round(progress)}%</span>
</div>
<span className="max-w-80 truncate text-xs text-zinc-500">
{loaded}/{total} {item}
</span>
</div>
);
}