chalatum Posted August 25, 2020 Share Posted August 25, 2020 Hello. I'm facing some issues with the GSAP isActive() function using React. I made an aside navigation/menu panel. When clicking on a button the navigation panel is deployed and its content follows (<ul/>, <li/>, etc.). For animating the navigation panel and its content I'm using a timeline in auseEffecthook like shown below. I want to use isActive() because I would like to prevent the user from spamming the toggle button. If the navigation toggle button is spammed by rapid clicks, the animation behave weirdly and the navigation content isn't displayed properly. So I checked the doc here: https://greensock.com/docs/v2/TweenMax/isActive() I tried to reproduce and it doesn't work. So I console logged tl.isActive() and it returns false all long the timeline run. I don't get it. Did I misunderstood something? I mean when the timeline is running it is supposed to return true, right? Can someone provides some help? Thanks. useEffect(() => { const tl = gsap.timeline(); const navRow1 = navRowRef.current; const navRow2 = navRow1.nextSibling; const navRow3 = navRow2.nextSibling; if (toggled === true) { tl.to(navigationRef.current, .9, { width: '100%', ease: 'power3.out' }).fromTo([navRow1.children[0], navRow2.children[0], navRow3.children[0]], { opacity: 0, x: -16 }, { opacity: 1, x: 0, ease: 'power3.out', duration: .6 }, "-=.45").fromTo([navRow1.children[1], navRow2.children[1], navRow3.children[1]], { opacity: 0, x: -22 }, { opacity: 1, x: 0, ease: 'power3.out', duration: .6 }, "-=.15").from(socialRef.current, .9, { opacity: 0, ease: 'power3.out' }, "-=.6"); console.log(tl.isActive()); } else { tl.to(innerNavRef.current, .45, { opacity: 0, ease: 'power3.out' }).to(navigationRef.current, .45, { width: '0%', ease: 'power3.out' }); } }, [toggled]); Link to comment Share on other sites More sharing options...
ZachSaucier Posted August 25, 2020 Share Posted August 25, 2020 Hey chalatum and welcome to the GreenSock forums. 1 hour ago, chalatum said: If the navigation toggle button is spammed by rapid clicks, the animation behave weirdly and the navigation content isn't displayed properly. That's because you're creating new tweens every single click and adding those to the timeline. We highly recommend that you create the animation outside of the click listener and just use control methods inside of the listener. Not doing so is one of the most common GSAP mistakes, as is adding tweens to timelines that have already been completed. I also write more about this concept in my article on animating efficiently. I'd try doing something like this (psuedo-code, untested): const tl = gsap.timeline({defaults: {ease: 'power3'}}); // Setup your animation useEffect(() => { const navRow1 = navRowRef.current; const navRow2 = navRow1.nextSibling; const navRow3 = navRow2.nextSibling; // In animation tl.to(navigationRef.current, { width: '100%', }).fromTo([navRow1.children[0], navRow2.children[0], navRow3.children[0]], { duration: .9, opacity: 0, x: -16 }, { opacity: 1, x: 0, duration: .6 }, "-=.45").fromTo([navRow1.children[1], navRow2.children[1], navRow3.children[1]], { opacity: 0, x: -22 }, { opacity: 1, x: 0, duration: .6 }, "-=.15").from(socialRef.current, { duration: .9, opacity: 0, }, "-=.6"); // Pause it tl.addPause(); // Out animation tl.to(innerNavRef.current, { duration: .45, opacity: 0, }).to(navigationRef.current, { duration: .45, width: '0%', }); }, []); // Control your animation on toggle useEffect(() => { if(!tl.isActive()) { if (toggled === true) { tl.play(0); } else { tl.play(); } } }, [toggled]); Keep in mind that toggled should not be able to be changed unless the tl is not active according to this setup. 1 Link to comment Share on other sites More sharing options...
chalatum Posted August 25, 2020 Author Share Posted August 25, 2020 @ZachSaucier Thank you very much for your answer. I now understand a bit more about the logic. 1) This is almost working trying your solution. The only issue that remains is the fact that the code after the addPause() seems to be unreachable (?) because on toggled false the out animation does not trigger and the navigation panel isn't moving and stays static. I tried to solve this but did not manage to, I'm pretty new at GSAP. 2) Also React is complaining in the terminal about the fact that tl is not passed as a dependency to those useEffect() hooks. But it does not make sense to pass it (breaks the app at some point)... I always wondered if it is a big deal not to pass a variable as a dependency to useEffect() despite the fact that React warns you. What do you think? Arthur Link to comment Share on other sites More sharing options...
ZachSaucier Posted August 25, 2020 Share Posted August 25, 2020 I'm not a React guy. Maybe one of the regulars who use React will step in and help. Link to comment Share on other sites More sharing options...
OSUblake Posted August 25, 2020 Share Posted August 25, 2020 Always use useRef if you want to access an animation elsewhere in your code. const tl = useRef(); // Setup your animation useEffect(() => { const navRow1 = navRowRef.current; const navRow2 = navRow1.nextSibling; const navRow3 = navRow2.nextSibling; // In animation tl.current = gsap.timeline({ defaults: {ease: 'power3'} }) .to(navigationRef.current, { width: '100%', }).fromTo([navRow1.children[0], navRow2.children[0], navRow3.children[0]], { duration: .9, opacity: 0, x: -16 }, { opacity: 1, x: 0, duration: .6 }, "-=.45").fromTo([navRow1.children[1], navRow2.children[1], navRow3.children[1]], { opacity: 0, x: -22 }, { opacity: 1, x: 0, duration: .6 }, "-=.15").from(socialRef.current, { duration: .9, opacity: 0, }, "-=.6"); // Pause it tl.current.addPause(); // Out animation tl.current.to(innerNavRef.current, { duration: .45, opacity: 0, }).to(navigationRef.current, { duration: .45, width: '0%', }); }, []); // Control your animation on toggle useEffect(() => { if(!tl.current.isActive()) { if (toggled === true) { tl.current.play(0); } else { tl.current.play(); } } }, [toggled, tl]); 2 Link to comment Share on other sites More sharing options...
chalatum Posted August 25, 2020 Author Share Posted August 25, 2020 Hello @OSUblake. Thanks. I gave a try with your code, but not on my navigation panel (will give a try on it tomorrow). Instead I tried it on small animations on nav/list items. I made a demo here: https://codesandbox.io/s/wizardly-shaw-9re8f?file=/src/ListItem.js Animations behave a bit weirdly: 1) First I don't really get why the "link-background" in ListItem is showing when page just loaded. It is supposed to have a width of 0 and not appearing on first load. 2) When I rapidly hover nav/list items the animation get stuck and "link-background" is showing while it is supposed to have disappear with a width of 0. Is my strategy ok to make this animation working fine? Link to comment Share on other sites More sharing options...
OSUblake Posted August 26, 2020 Share Posted August 26, 2020 I didn't test that code. Just showing how to access an animation elsewhere. The addPause method that zach did probably isn't going to work well for hovering. What you originally posted should work. Maybe try setting overwrite to "auto" for your animations. Link to comment Share on other sites More sharing options...
chalatum Posted August 26, 2020 Author Share Posted August 26, 2020 12 hours ago, OSUblake said: What you originally posted should work. Maybe try setting overwrite to "auto" for your animations. Unfortunately it's not working very well. What do you mean by setting overwrite to "auto"? I tried some stuff in the code sand box today but did not manage to find a solution. When I hover to fast on a nav item, the timeline get stuck in its first part and does not reach the second part. If I get ride of the addPause() the whole timeline runs, I don't want that. Link to comment Share on other sites More sharing options...
OSUblake Posted August 26, 2020 Share Posted August 26, 2020 Here's a demo I posted earlier. You can apply the same technique to hover animations. https://codesandbox.io/s/suspicious-violet-icn19?file=/src/components/atom/Menu.js 2 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now