Jump to content
Search Community

useGSAP understanding

Leptitnouveau test
Moderator Tag

Recommended Posts

Hello,

 

I've started my React journey recently.

For my final university college project, I want to create a "Your own adventure webcomic". I want to animate the every panels and in order to do so I had to use GSAP or "useGSAP" (I am proud of this one).

 

I have watched those two videos to understand how it works:

https://www.youtube.com/watch?v=DwU72sp_gGI

https://youtu.be/l0aI8Ecumy8

 

But I am not sure if I have fully understood how it works. useGSAP automatically revert the animation at the end, so does it mean that I am not supposed to see things like this once the animation finished?

image.png.3f1d605d774762c5466c86d032c4c950.png

Or is it only when the component is dismounted?

 

I also wanted to ask if I use it properly. So here is an example of how I have used it in my code:

 

 const [isMounted, setIsMounted] = useState(false)
const shakingRef = useRef(gsap.timeline({ repeat: 2, repeatDelay: 0 }));
 
useEffect(() => {
    setIsMounted(true);
  }, []);
  useGSAP(
    () => {
      if (isMounted == true) {
        if (healthRef.current > elvan.health) {
          shakingRef.current
            .to(elvanRef.current, { xPercent: -5, yPercent: -5, duration: 0.1 })
            .to(elvanRef.current, { xPercent: -0, yPercent: -0, duration: 0 })
            .to(elvanRef.current, { xPercent: 5, yPercent: 5, duration: 0.1 })
            .to(elvanRef.current, { xPercent: -0, yPercent: -0, duration: 0 });
        }
      }
    },
    {
      dependencies: [elvan.health],
      scope: elvanRef.current,
    }
  );

 

Thank you in advance for your answer (And sorry if I have made some mistakes, English is not my mother tongue).

Link to comment
Share on other sites

Hello again,

There is something else that I wanted to understand. I managed to resolve the problem but I do not understand how it resolved it.

 

I wanted to animate a div, in order to do so I have first created a ref element in the parent component and I have attached it to this div (Which stands in the children component). I have animated the div with a timeline and useGSAP (that are also in the parent component) and I have said that onComplete I want to revert the animation. But I have noticed two weird things:

 

- first, when the component is mounted for the first time in strict mode, I saw that the ref returned undifined instead of the div element before showing the div element once mounted a second time.

- secondly, when I have added to revert the animation, the animation did not play at all.

 

I manage to resolve this issue by passing the ref and the useGSAP directly to the children component, but I do not understand how it resolved the problem so if anyone know what happened please let me know.

 

How the code was before:

Parent component:

 

  const animatedRef = useRef(null);
  const timelineAnimationRef = useRef(
    gsap.timeline({
      repeat: 6,
      repeatDelay: 0,
      onComplete: () => {
        console.log("animation finished");
        if (animatedRef.current && timelineAnimationRef.current) {
          // timelineAnimationRef.current.revert();
        }
      },
    })
  );
  useGSAP(
    () => {
      if (animatedRef.current) {
        console.log(animatedRef.current.id);
      }
      if (animatedRef.current && animatedRef.current.id == 2) {
        timelineAnimationRef.current
          .to(animatedRef.current, { rotate: "-5deg", duration: 0.06 })
          .to(animatedRef.current, {
            rotate: "5deg",
            duration: 0.06,
          });
      }
    },
    { dependencies: [displayToNumber, content] }
  );
 
return (
    <div id="story" className="container w-4/6 flex flex-col items-center">
      {content.map(
        (contentObject, index) =>
          displayToNumber >= index && (
            <StoryFragment
              animatedRef={animatedRef}
            />
          )
      )}
     </div>
)

Children component:

 

  return (
          <div
            ref={animatedRef}
            id={content.id}
            className={`w-full h-min relative overflow-hidden`}
          >
          </div>
)
 
Now everything has been sent to the root of the children component
Link to comment
Share on other sites

Hi,

 

On 5/18/2024 at 9:21 AM, Leptitnouveau said:

useGSAP automatically revert the animation at the end, so does it mean that I am not supposed to see things like this once the animation finished?

No, what useGSAP does is revert everything inside it's scope when the component unmounts:

https://gsap.com/docs/v3/GSAP/Tween/revert()

 

Once the animation is completed nothing happens in that sense, everything is still there because you might want to restart your animation at a later moment. Think about a modal or any other re-usable GSAP instance. What would happen if open the modal and remove all the styles applied to it by GSAP? The modal would disappear, whoosh! and the user would be like.... "isn't supposed to be a modal here?! 🤔", that's just bad UX. Or think about a menu overlay that is toggled open/close, you open the menu and then when the animation is completed whoosh!. See the problem?

 

Also this is wrong:

const timelineAnimationRef = useRef(
  gsap.timeline({
    repeat: 6,
    repeatDelay: 0,
    onComplete: () => {
      console.log("animation finished");
      if (animatedRef.current && timelineAnimationRef.current) {
        // timelineAnimationRef.current.revert();
      }
    },
  })
);
useGSAP(
  () => {
    if (animatedRef.current) {
      console.log(animatedRef.current.id);
    }
    if (animatedRef.current && animatedRef.current.id == 2) {
      timelineAnimationRef.current
        .to(animatedRef.current, { rotate: "-5deg", duration: 0.06 })
        .to(animatedRef.current, {
        rotate: "5deg",
        duration: 0.06,
      });
    }
  },
  { dependencies: [displayToNumber, content] }
);

Is better to create the GSAP instances inside the useGSAP hook, with that code the useGSAP code has no way to revert that timeline, so it would be there after the component unmounts which could lead to unexpected behaviour. Also that GSAP Timeline is created everytime the component is re-rendered. This is the recommended way:

const timelineAnimationRef = useRef();
useGSAP(
  () => {
    if (animatedRef.current) {
      console.log(animatedRef.current.id);
    }
    if (animatedRef.current && animatedRef.current.id == 2) {
      const tl = gsap.timeline({
        repeat: 6,
      })
      tl
        .to(animatedRef.current, { rotate: "-5deg", duration: 0.06 })
        .to(animatedRef.current, {
        rotate: "5deg",
        duration: 0.06,
      });
      timelineAnimationRef.current = tl;
    }
  },
  { dependencies: [displayToNumber, content] }
);
On 5/18/2024 at 5:39 PM, Leptitnouveau said:

I manage to resolve this issue by passing the ref and the useGSAP directly to the children component, but I do not understand how it resolved the problem

Honestly I'm a bit confused about what exactly are you passing as a prop to the child component. My recommendation (and this is just a personal preference), I try to keep the child<->parent communications to a minimum in React. If possible I create every GSAP instance in the component where the elements will be rendered and if that is not an option keep the GSAP Tween/Timeline on a parent component, but only as a last resort.

 

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...