I'm using useProgress
from react three drei. Apparently, this is used to keep track of the loading state from the models on the scene. I have created a loading screen with a progress bar in which I will be showing the loading state from this progress. But, In all occasions, the progress always goes from 0 to 100 instantly, it does not go from 0...45...50..90.100. Which I believe is wrong, since I have some large models.
This is the base experience component.
import { Dispatch, SetStateAction, Suspense, useRef, useState } from "react";
import OrbitControls from "./components/OrbitControls";
import { Perf } from "r3f-perf";
import { ObjectForReference } from "./components/ObjectForReference";
import * as THREE from "three";
import Room from "./components/Room";
import useLevaControls from "./hook/useLevaControls";
import OverlayLoading from "./components/OverlayLoading";
interface ExperienceProps {
setHiddenLeva: Dispatch<SetStateAction<boolean>>;
}
export default function Experience({ setHiddenLeva }: ExperienceProps) {
const invisibleObjectRef = useRef<THREE.Mesh | null>(null);
const [orbitControlsDisabled, setOrbitControlsDisabled] =
useState<boolean>(false);
// Hide overaly
const [hideOverlay, setHideOverlay] = useState<boolean>(false);
const [isPointerOnHtml, setIsPointerOnHtml] = useState<boolean>(false);
const { viewWebpage, showPerformace } = useLevaControls();
return (
<>
<color args={["#2E282A"]} attach="background" />
{showPerformace && <Perf position="top-left" />}
<OrbitControls
invisibleObjectRef={invisibleObjectRef}
isPointerOnHtml={isPointerOnHtml}
focusOnHtml={viewWebpage}
disabled={orbitControlsDisabled}
/>
<ObjectForReference
meshRef={invisibleObjectRef}
position={new THREE.Vector3(-4, 1.7, 0)}
/>
{!hideOverlay && (
<OverlayLoading
setOrbitControlsDisabled={setOrbitControlsDisabled}
setHiddenLeva={setHiddenLeva}
setHideOverlay={setHideOverlay}
/>
)}
<Suspense>
<Room
setIsPointerOnHtml={setIsPointerOnHtml}
isFocusOnHtml={viewWebpage}
/>
</Suspense>
</>
);
}
As you can see I added some suspense on the Room component so I can render the OveralyLoading first.
This is to render some presentation data:
import "./index.css";
import { useState, useCallback, Dispatch, SetStateAction } from "react";
import { Html } from "@react-three/drei";
import IntroOne from "../IntroScreens/IntroOne";
import IntroTwo from "../IntroScreens/IntroTwo";
import IntroThree from "../IntroScreens/IntroThree";
interface HtmlOverlayProps {
setOrbitControlsDisabled: Dispatch<SetStateAction<boolean>>;
setHiddenLeva: Dispatch<SetStateAction<boolean>>;
setHideOverlay: Dispatch<SetStateAction<boolean>>;
planeMeshRef: any;
}
export default function HtmlOverlay({
setHideOverlay,
setHiddenLeva,
setOrbitControlsDisabled,
planeMeshRef,
}: HtmlOverlayProps) {
const [presentationScreens, setPresentationScreens] = useState(0);
const handlePresentationScreen = useCallback(() => {
switch (presentationScreens) {
case 0:
return <IntroOne setPresentationScreens={setPresentationScreens} />;
case 1:
return <IntroTwo setPresentationScreens={setPresentationScreens} />;
case 2:
return (
<IntroThree
setHideOverlay={setHideOverlay}
setHiddenLeva={setHiddenLeva}
setOrbitControlsDisabled={setOrbitControlsDisabled}
planeMeshRef={planeMeshRef}
/>
);
}
}, [
planeMeshRef,
presentationScreens,
setHiddenLeva,
setHideOverlay,
setOrbitControlsDisabled,
]);
return (
<Html fullscreen className="htmlComponent">
{handlePresentationScreen()}
</Html>
);
}
The screen inside the Overlay loading, keeps track of the progress:
import { Dispatch, SetStateAction, useEffect } from "react";
import { useProgress } from "@react-three/drei";
import gsap from "gsap";
interface IntroOneProps {
setPresentationScreens: Dispatch<SetStateAction<number>>;
}
export default function IntroOne({ setPresentationScreens }: IntroOneProps) {
const { progress } = useProgress();
useEffect(() => {
if (progress === 100) {
setTimeout(() => {
gsap.to(".opacityControl", {
opacity: 0,
onComplete: () => {
setPresentationScreens(1);
},
});
}, 1500);
}
}, [progress, setPresentationScreens]);
return (
<div className="localHtml opacityControl">
<div className="commonHtml">
<div style={{ marginBottom: 20 }}>
<span className="introText">We are loading your experience</span>
</div>
<div className="progressBar">
<div
style={{
height: "100%",
borderRadius: 10,
width: `${progress}%`,
backgroundColor: "#0061FF",
}}
></div>
</div>
</div>
</div>
);
}