Jump to content
Search Community

Handle animations on resize with React

chalatum test
Moderator Tag

Recommended Posts

Hello.

 

I've got a drawer navbar in my app which mounts/unmounts - slides in/slides out on toggle.  On laptop it's at the left of the window, and on smaller devices it's at the top. Depending on the window size I need to animate the drawer navbar and its content a bit differently (like width on laptop, and height on tablet and phone). I need to achieve that on window resize.

 

I tried to solve that with a custom hook which returns size.width (this hook works fine). I passed size.width as a dependency to useEffect() as shown below. But it's not working. On resize the drawer navbar content seems to collapse and disappear.

 

I know I could solve my problem by creating three different drawer components with their own timeline, mounting/unmounting on window resize, but I guess this is not an optimized solution. So my question is: how can I handle that in one single component?

 

const DrawerNavBar = () => {

    const value = useNav();
    const size = useWindowSize();

    const element1Ref = useRef(null);
    const element2Ref = useRef(null);
    const element3Ref = useRef(null);

	const tl = useRef(null);

    useEffect(() => {

        if (size.width >= 1280) {

            tl.current = gsap.timeline({ defaults: { ease: 'power2.out' }, paused: true })
                //.to(element1Ref.current...)
                //.fromTo(element2Ref.current...)
                //.fromTo(element3Ref.current...)
                //etc.

        } else if (size.width <= 834) {

            tl.current = gsap.timeline({ defaults: { ease: 'power3.out' }, paused: true })
                //.to(element1Ref.current...)
                //.fromTo(element2Ref.current...)
                //.fromTo(element3Ref.current...)
                //etc.

        }

    }, [size.width]);

useEffect(() => {
        if (!tl.current.isActive()) {
            if (value) {
                tl.current.play(0).addPause(1.1);
            } else {
                tl.current.play(1.1);
            }
            return () => tl.current.kill();
        }
    }, [value, tl]);

 

 

Link to comment
Share on other sites

Hello Zach. Thank you for those tips but I'm still a bit lost... I don't really get  set(element, {clearProps: true})  (I checked the doc) Am I supposed to apply it at the end of each timelines in my first useEffect()? Maybe it sounds silly but I also don't understand which reference/element I'm supposed to target with it.

 

Also I already killed the old timeline in the code above, so I guess this point is fine?

 

 

 

 

 

 

Link to comment
Share on other sites

Hi,

 

Zach's advice for using clear props should be used here:

useEffect(() => {
  if (size.width >= 1280) {
    gsap.set([/*all the elements in the menu*/], {clearProps: true});
    tl.current = gsap.timeline({ defaults: { ease: 'power2.out' }, paused: true })
    //.to(element1Ref.current...)
    //.fromTo(element2Ref.current...)
    //.fromTo(element3Ref.current...)
    //etc.

  } else if (size.width <= 834) {
    gsap.set([/*all the elements in the menu*/], {clearProps: true});
    tl.current = gsap.timeline({ defaults: { ease: 'power3.out' }, paused: true })
    //.to(element1Ref.current...)
    //.fromTo(element2Ref.current...)
    //.fromTo(element3Ref.current...)
    //etc.

  }

}, [size.width]);

That will basically remove all the styles applied by GSAP previously and leave it with the base styles declared in the CSS.

 

Happy Tweening!!!

  • Like 3
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...