Object is reloading every time I scroll

68 views Asked by At

I have a model of a 3D fridge, and loading it is successful. I am trying to make it drag across the screen when the user scrolls, and moving the div works, however the 3d object itself refreshes. Please watch the attached video to see how it keeps refreshing.

Is there a special setting for me to specify in the canvas whenever I initialize the model? I tried looking around multiple forums and couldn't find a fix for my problem.

https://youtu.be/MxHXLc-C3i4

Code:

import React from 'react'
import Navbar from '../components/Navbar';

import {useRef, useEffect} from 'react';
import {useGLTF, Stage, PresentationControls, OrbitControls, useScroll} from '@react-three/drei';
import {Canvas} from '@react-three/fiber';
import { useLoader, useFrame, useThree } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { Suspense } from 'react'
import ModelViewer from '../components/ModelViewer';
import * as THREE from 'three';

function Model(props){
  const {scene} = useGLTF("model.glb");

  useThree(({camera}) => {

    camera.position.set(-180, 20, -160);

  });

  // let model = useLoader(GLTFLoader, "model.glb");

  scene.traverse(child => {
    if (child.isMesh) {
        child.castShadow = true
        child.receiveShadow = true
    }
  });



  return <primitive object={scene} {...props} />;
}



export default function Home(props) {

  const groupRef = useRef();

  const [scrollY, setScrollY] = React.useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollY(window.scrollY);
    };
    handleScroll();

    window.addEventListener("scroll", handleScroll);
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  });

  useEffect(() => {

    // as the user scrolls, the "fridge" div will move to center of screen
    let fridge = document.getElementById('fridge');

    window.addEventListener('scroll', () => {

      // make it smooth 
      //       fridge.style.transform = "translateX(" + -midScreenX + "px)";
      // for every scrollY, move the fridge to the left by 1px
      for(let i = 0; i < scrollY; i++){
        fridge.style.transform = "translateX(" + -i + "px)";
      }
    });

  });

  return (
    
    <section className="">
        <Navbar />
        
        <div className="flex items-center justify-center">
        <div className="flex flex-col md:flex-row w-9/12 justify-center items-center h-screen">
          <div className="flex items-center bg-gray-300 w-full">
            <div className="flex flex-col">
                <h1 className="font-CreteRoundRegular text-5xl text-center md:text-left">KitchIN</h1>
                <p className="font-CreteRoundRegular text-xl text-center md:text-left">A smart fridge that helps you keep track of your food.</p>
            </div>
          </div>
          <div className="md:w-1/2 w-full h-5/6 bg-red-200" id="fridge">
            <Canvas>
              {/* <Suspense fallback={null}>
                <Stage>
                  <Model />
                      <OrbitControls enableZoom={false} />
                </Stage>
              </Suspense> */}
              <Suspense fallback={null}>
                <Stage>
                <Model />
                <OrbitControls enableZoom={false} />
                </Stage>
                
              </Suspense> 
            </Canvas>
          </div>
          </div>

        </div>
        <div className="flex h-screen">
            <h1>Hello</h1>
          </div>
    </section>
  )
}

useGLTF.preload("modern_fridge.glb");



1

There are 1 answers

0
Timsib Adnap On
import {
    OrbitControls,
    PresentationControls,
    Stage,
    useGLTF,
    useScroll,
} from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { useFrame, useLoader, useThree } from "@react-three/fiber";
import React from "react";
import { useEffect, useRef, useState } from "react";
import { Suspense } from "react";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

import ModelViewer from "../components/ModelViewer";
import Navbar from "../components/Navbar";

function Model(props) {
    const { scene } = useGLTF("model.glb");

    useThree(({ camera }) => {
        camera.position.set(-180, 20, -160);
    });

    // let model = useLoader(GLTFLoader, "model.glb");

    scene.traverse((child) => {
        if (child.isMesh) {
            child.castShadow = true;
            child.receiveShadow = true;
        }
    });

    return <primitive object={scene} {...props} />;
}

export default function Home(props) {
    const groupRef = useRef();

    const [scrollY, setScrollY] = useState(0);

    useEffect(() => {
        const handleScroll = () => {
            setScrollY(window.scrollY);
        };
        handleScroll();

        window.addEventListener("scroll", handleScroll);
        return () => {
            window.removeEventListener("scroll", handleScroll);
        };
    }, []);

    useEffect(() => {
        // as the user scrolls, the "fridge" div will move to center of screen
        let fridge = document.getElementById("fridge");

        window.addEventListener("scroll", () => {
            for (let i = 0; i < scrollY; i++) {
                fridge.style.transform = "translateX(" + -i + "px)";
            }
        });
    }, []);

    return (
        <section className="">
            <Navbar />

            <div className="flex items-center justify-center">
                <div className="flex flex-col md:flex-row w-9/12 justify-center items-center h-screen">
                    <div className="flex items-center bg-gray-300 w-full">
                        <div className="flex flex-col">
                            <h1 className="font-CreteRoundRegular text-5xl text-center md:text-left">
                                KitchIN
                            </h1>
                            <p className="font-CreteRoundRegular text-xl text-center md:text-left">
                                A smart fridge that helps you keep track of your
                                food.
                            </p>
                        </div>
                    </div>
                    <div
                        className="md:w-1/2 w-full h-5/6 bg-red-200"
                        id="fridge"
                    >
                        <Canvas>
                            <Suspense fallback={null}>
                                <Stage>
                                    <Model />
                                    <OrbitControls enableZoom={false} />
                                </Stage>
                            </Suspense>
                        </Canvas>
                    </div>
                </div>
            </div>
            <div className="flex h-screen">
                <h1>Hello</h1>
            </div>
        </section>
    );
}

useGLTF.preload("modern_fridge.glb");

You need to add empty parameter lists to the useEffect hook to prevent repeated re-renders

Check this StackOverflow question for further reference on this