Jump to content


  • Posts

  • Joined

  • Last visited

chalatum's Achievements



  1. Don't mind, I was on the wrong path. I shifted to Reac-Transition-Group to reach my goal. It's now working.
  2. Hello. I'm crafting a carousel with React, using GSAP timeline for image transitions. I tried during several hours to make the timeline pause on mouse enter and restart on mouse leave but I wasn't successful. I used and read the documentation about timeline() but even with that I just failed to manage doing what I want. Below is the code of my functional component. I'm using setInterval() setTimeout() and useState() to mount my images one after another. When entering "carousel-wrapper" I would like the animation to pause in order to see the current active image and stay on it. Once removing the cursor from this area I would like the timeline to restart smoothly. All I got with my tries now are glitches, animation not pausing despite using resume(),addPause(), kill()... Frustrating... Thanks by advance for any help. const MyComponent = () => { const [state, setState] = useState({ isActive1: true, isActive2: false, isActive3: false }) const [count, setCount] = useState(0) const [mod, setMod] = useState(0) const [entered, setEntered] = useState(null) const tl = useRef(null) const interval = useRef(null) const timeout = useRef(null) useEffect(() => { interval.current = setInterval(() => { setCount(prevState => ++prevState) }, 8200) if (entered) { clearInterval(interval.current) interval.current = null setState(prevState => ({ isActive1: prevState.isActive1, isActive2: prevState.isActive2, isActive3: prevState.isActive3 })) } return () => { clearInterval(interval.current) interval.current = null } }, [entered]) useEffect(() => { timeout.current = setTimeout(() => { setMod(count % 3) }, 1250) return () => { clearTimeout(timeout.current) timeout.current = null } }, [count]) useEffect(() => { setState({ isActive1: mod === 0 ? true : false, isActive2: mod === 1 ? true : false, isActive3: mod === 2 ? true : false }) }, [mod]) useEffect(() => { if (!entered) { tl.current = gsap.timeline() .fromTo('.img-wrapper', { left: 0, width: 0, opacity: 0 }, { duration: 1.5, opacity: 1, width: '100%', ease: 'power3.inOut', }) .fromTo('.img-wrapper', { left: 'unset', right: 0, opacity: 1, width: '100%', }, { duration: 1.3, width: 0, opacity: 0, ease: 'power4.inOut' }, "+=5.4") .to('.img-wrapper', { duration: 0, right: 'unset' }) } else if (entered) { // What I'm supposed to put here? } }, [state, entered]) return ( <div className='hero'> <div className='carousel-wrapper' onMouseEnter={() => setEntered(prevState => !prevState)} onMouseLeave={() => setEntered(prevState => !prevState)} > <h3 className='carousel-title'>Title</h3> <div className='carousel'> <div className='img-wrapper'> {state.isActive1 && <img src='images/img_1.jpg' alt='blabla' />} {state.isActive2 && <img src='images/img_2.jpg' alt='blabla' />} {state.isActive3 && <img src='images/img_3.jpg' alt='blabla' />} </div> </div> </div> </div> ) } export default Hero
  3. 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?
  4. 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]);
  5. 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.
  6. 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?
  7. @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
  8. 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]);