Levin Riegner Posted April 28, 2023 Posted April 28, 2023 I have created this React component which should be repeating infinitely, but it only plays once. I feel like im going insane, why is it only playing once?? const Marquee = React.forwardRef((props, ref) => { const first = useRef(); const last = useRef(); useLayoutEffect(() => { const tl = gsap.to(first.current, { xPercent: -100, repeat: -1, duration: 5, ease: 'none', repeatRefresh: true, }); const tl2 = gsap.to(last.current, { xPercent: -100, repeat: -1, duration: 5, ease: 'none', repeatRefresh: true, }); }, []); return ( <Jacket isPaused={props.isPaused} ref={ref}> <div> <ul ref={first}> {props.text.map(({ word, uid }) => ( <li key={uid} className='el'> {word} – </li> ))} </ul> {/* Dupl */} <ul aria-hidden='true' ref={last}> {props.text.map(({ word, uid }) => ( <li className='el' key={uid}> {word} – </li> ))} </ul> </div> </Jacket> ); }); For reference:https://codesandbox.io/s/divine-sun-7kksyk?file=/src/Marquee/index.jsx See the Pen Marquee by s (@s) on CodePen.
Levin Riegner Posted April 28, 2023 Author Posted April 28, 2023 Also, even trying to set an amount of repeats has no effect - I tried 3 just to see, but it plays once only, ever.
Levin Riegner Posted April 28, 2023 Author Posted April 28, 2023 Okay I got it working with this code - but it doesnt make sense why this would work vs the other const Marquee = React.forwardRef((props, ref) => { const first = useRef(); const last = useRef(); useLayoutEffect(() => { const width1 = first.current.offsetWidth; const width2 = first.current.offsetWidth; const timeline1 = gsap.timeline(); const timeline2 = gsap.timeline(); timeline1.fromTo( first.current, { xPercent: 0, }, { xPercent: -100, repeat: -1, repeatRefresh: true, duration: 5, ease: 'none', } ); timeline2.fromTo( last.current, { xPercent: 0, }, { xPercent: -100, repeat: -1, repeatRefresh: true, duration: 5, ease: 'none', } ); }, []); return ( <Jacket isPaused={props.isPaused} ref={ref}> <div> <ul ref={first}> {props.text.map(({ word, uid }) => ( <li key={uid} className='el'> {word} – </li> ))} </ul> {/* Dupl */} <ul aria-hidden='true' ref={last}> {props.text.map(({ word, uid }) => ( <li className='el' key={uid}> {word} – </li> ))} </ul> </div> </Jacket> ); });
GreenSock Posted April 28, 2023 Posted April 28, 2023 That's because you set repeatRefresh: true on those tweens. I wonder what your goal was with that since you don't have any dynamic values so it seems totally useless. When you have repeatRefresh: true, that tells the tween to flush all recorded starting values on each repeat cycle and re-parse everything again. So let's say you animate to xPercent: -100 and repeat infinitely but have repeatRefresh: true. Assuming xPercent is currently 0 at the time you create that animation, your to() tween animates from whatever it current is (0) to -100. Great. Then, since you set repeatRefresh: true, it will then flush any recorded values and re-instantiate that .to() tween. So at this moment xPercent is -100...and your to() tween says "animate it from the current value (-100) to -100" which is of course no change. It'll look broken but GSAP is doing exactly what you told it to do. It's a logic issue in your code. The reason it worked when you switched to using .fromTo() tweens is because you're defining BOTH the start AND end values. The simple solution: remove repeatRefresh That's there for dynamic values, like function-based ones or random strings, etc. It might be good to read the docs on that feature. 2
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