Jump to content
Search Community

Help: Does my useGSAP function need to return anything? (React Three Fiber)

ineslucas test
Moderator Tag

Recommended Posts

 When hosted on Vercel, this React Three Fiber canvas animation sometimes works and other times it really doesn't. I've already had to remove a scroll trigger as it was messing a lot with my hover/mouse events, unfortunately.

What can I do so that all the objects are equally moved by the animation every time? I've already included a loader component and all my objects are within a <Suspense fallback={null}> tag. Does my useGSAP function need to return anything?
 

import React, { useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import ToolboxWithObjects from "./ToolboxWithObjects.js";

export default function Experience({ setIsHoveringLeicaM6 })
{
  {/** Experience is a component inside the Canvas - only place where we can use R3F hooks */}
  const { camera, gl } = useThree();
  const keyboardRef = useRef();
  const microphoneRef = useRef();
  const leicaM6Ref = useRef();
  const threadRef = useRef();
  const businessCardRef = useRef();
  const businessCardHorizontalRef = useRef();
  const fullToolboxRef = useRef();

  useGSAP(() => { // useGSAP instead of useLayoutEffect
    const tl = gsap.timeline({ });

    if (businessCardHorizontalRef.current) {
      // Mid position
      tl.to(businessCardHorizontalRef.current.position, { x: 0, y: 1, z: 0.075, duration: 1 }, 0);
      tl.to(businessCardHorizontalRef.current.rotation, { x: -0.135, y: 0, z: 0, duration: 1 }, 0);
      // Final position + rotation inside the box
      tl.to(businessCardHorizontalRef.current.position, { x: 0, y: 0, z: 0.075, duration: 2 }, 2);
      tl.to(businessCardHorizontalRef.current.rotation, { x: -0.135, y: 0, z: 0, duration: 2 }, 2);
    }

    if (businessCardRef.current) {
      // Mid position
      tl.to(businessCardRef.current.position, { x: 0.005, y: 3.3, z: 0, duration: 2 }, 0);
      tl.to(businessCardRef.current.rotation, { x: 0, y: 0, z: 0, duration: 2 }, 0);
      // Final position + rotation inside the box
      tl.to(businessCardRef.current.position, { x: 0.005, y: 0, z: 0, duration: 2 }, 2);
      tl.to(businessCardRef.current.rotation, { x: 0, y: 0, z: 0, duration: 2 }, 2);
    }

    if (threadRef.current) {
      // Mid position
      tl.to(threadRef.current.position, { x: 1.6, y: 4, z: -0.4, duration: 2 }, 0);
      // Final position + rotation inside the box
      tl.to(threadRef.current.position, { x: 1.5, y: -0.18, z: -0.4, duration: 2 }, 2);
      tl.to(threadRef.current.rotation, { x: 0, y: 0.08, z: 1.6, duration: 4 }, 0);
    }

    if (leicaM6Ref.current) {
      // Mid position
      tl.to(leicaM6Ref.current.rotation, { x: 0, y: 0, z: 0.1, duration: 2 }, 0);
      // Final position + rotation inside the box
      tl.to(leicaM6Ref.current.position, { x: 1.015, y: -0.27, z: 0.47, duration: 2 }, 2);
      tl.to(leicaM6Ref.current.rotation, { x: 0, y: 0, z: 0.1, duration: 2 }, 2);
    }

    if (keyboardRef.current) {
      // Mid position
      tl.to(keyboardRef.current.position, { x: -0.6, y: 3, z: 0.8, duration: 1 }, 1);
      // Final position + rotation inside the box
      tl.to(keyboardRef.current.position, { x: -0.6, y: 0.13, z: 0.62, duration: 2 }, 2);
      tl.to(keyboardRef.current.rotation, { x: -1.6, y: -0.75, z: -1.6, duration: 2 }, 2);
    }

    if (microphoneRef.current) {
      // mid position
      tl.to(microphoneRef.current.position, { x: 0.3, y: 2.8, z: -1.7, duration: 2 }, 0);
      tl.to(microphoneRef.current.rotation, { x: 5, y: 0.02, z: 1.6, duration: 2 }, 0);
      // Final position + rotation inside the box
      tl.to(microphoneRef.current.position, { x: 0.3, y: 0.4, z: -1.7, duration: 2 }, 2);
      tl.to(microphoneRef.current.rotation, { x: 5, y: 0.02, z: 1.6, duration: 2 }, 2);
    }

    tl.to(camera.rotation, { x: -0.6, y: 0, z: 0, duration: 3 }, 0);
    tl.to(camera.position, { x: 0, y: 4, z: 6, duration: 3 }, 0);

    if (fullToolboxRef.current) {
      // objects could fall down inside the box
      tl.to(fullToolboxRef.current.rotation, { x: 0, y: -1.525, z: 0, duration: 1 }, 4);
      tl.to(camera.rotation, { x: -1.25, y: 0, z: 0, duration: 1 }, 4);
      tl.to(camera.position, { x: 0, y: 6, z: 2.1, duration: 1 }, 4);
    }
  }, []);

  return <>
    <group position-y={-0.6}>
      <ToolboxWithObjects
        keyboardRef={keyboardRef} microphoneRef={microphoneRef} leicaM6Ref={leicaM6Ref} threadRef={threadRef} businessCardRef={businessCardRef} businessCardHorizontalRef={businessCardHorizontalRef} fullToolboxRef={fullToolboxRef}
        setIsHoveringLeicaM6={setIsHoveringLeicaM6} />
    </group>
  </>
}

 

Link to comment
Share on other sites

It's very difficult to troubleshoot without a minimal demo; the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

Hi,

 

Besides echoing the need for a minimal demo my best guess here is that you have all this conditional logic blocks depending on whether or not one of those refs is truthy:

useGSAP(() => { // useGSAP instead of useLayoutEffect
  const tl = gsap.timeline({ });

  if (businessCardHorizontalRef.current) {
  }

  if (businessCardRef.current) {
  }

  if (threadRef.current) {
  }

  if (leicaM6Ref.current) {
  }

  if (keyboardRef.current) {
  }

  if (microphoneRef.current) {
  }

  tl.to(camera.rotation, { x: -0.6, y: 0, z: 0, duration: 3 }, 0);
  tl.to(camera.position, { x: 0, y: 4, z: 6, duration: 3 }, 0);

  if (fullToolboxRef.current) {
  }
}, []);

But that entire part of your code is running only once when the component gets mounted, maybe you need to run that logic at another point during the lifecycle of your app.

 

Finally the useGSAP hook accepts an object as the second parameter not an array:

useGSAP(() => {}, {
  scope: myRef,
  dependencies: [],
  revertOnUpdate: true,
});

By default the hook uses an empty array for the dependencies, so there is no need to pass that.

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...