Muhammad Saqib
Muhammad Saqib

Reputation: 360

React three Fiber Model Preloader is transformed by default?

I have added a preloader to my 3D model in a React Three Fiber (R3F) project. I want to display a placeholder image while the model is loading. Once the model has finished loading, R3F will replace the placeholder image with the actual 3D model.

This is my canvas component.

<Canvas
  className="three-view"
  shadows
  style={{ minHeight: "450px", position: "relative" }}
>
  <Suspense
    fallback={
      <Html>
        <ModelLoader />
      </Html>
    }
  >
    <Environment files="/models/environment/all-direction.hdr" />
    <PerspectiveCamera makeDefault rotation={[0, 0, 0]} position={[0, 0, 2]} zoom={8} />
    <ambientLight intensity={3} />
    <OrbitControls
      ref={controlsRef}
      enablePan={false}
      enableZoom={true}
      enableRotate={true}
      autoRotate={true}
      autoRotateSpeed={3}
      minDistance={1}
      maxDistance={1.5}
    />
    <Iphone16Model url={`/models/iphone/${modelUrl}/iphone-16-pro-max-${modelUrl}.gltf`} />
  </Suspense>
</Canvas>

and this is my ModelLoader component

import { useProgress } from "@react-three/drei";
import ModelPlaceholder from "/assets/images/excellent.webp";

export const ModelLoader = () => {
  const { progress } = useProgress();

  return (
    <div className="model-preloader">
      <div className="model-preloader__img">
        <img src={ModelPlaceholder} alt="Model Placeholder" />
      </div>
      <span className="model-preloader__progress">
        {progress.toFixed(2)}%
      </span>
    </div>
  );
};

I added an image to my canvas, but it isn't centered. When I tried to use position: absolute; top: 0; left: 0; width: 100%; height: 100%; to cover the entire canvas, it didn’t work as expected. I couldn't find an efficient solution. Any suggestions?

Upvotes: 0

Views: 40

Answers (1)

chain saw
chain saw

Reputation: 1

I have ever faced like in your case. I think it is because of <Html> tag in your code.

In fallback, input function, no <ModelLoader> component. Then define that function in same component. In that function, return component.

Here is code:

const loader = () => {
 return (
    <ModelLoader>
  )
}
return (
<Canvas
  className="three-view"
  shadows
  style={{ minHeight: "450px", position: "relative" }}
>
  <Suspense
    fallback={loader}
  >
    <Environment files="/models/environment/all-direction.hdr" />
    <PerspectiveCamera makeDefault rotation={[0, 0, 0]} position={[0, 0, 2]} zoom={8} />
    <ambientLight intensity={3} />
    <OrbitControls
      ref={controlsRef}
      enablePan={false}
      enableZoom={true}
      enableRotate={true}
      autoRotate={true}
      autoRotateSpeed={3}
      minDistance={1}
      maxDistance={1.5}
    />
    <Iphone16Model url={`/models/iphone/${modelUrl}/iphone-16-pro-max-${modelUrl}.gltf`} />
  </Suspense>
</Canvas>
)

Upvotes: 0

Related Questions