SteveS Posted May 19, 2022 Share Posted May 19, 2022 I am trying to make a react component that produces a parallax effect on its child component. To do so, I am creating a scrollTrigger that starts when the element enters the viewport, and ends when it leaves. However, this requires me to use the element as the trigger and animate it. I'm aware that this is usually recommended against for a variety of reasons, however, in this case I find it works with one exception. Since I want the parallax to be controlled by the initial position of the element from start to end, the default behavior of the trigger bounds not updating is exactly what I want. However, I am using a .fromTo tween. As a result, the trigger positions are calculated based on the "from" position when instead I want them to be calculated from the elements default position. Is there a way I can get the scrollTrigger to calculate the trigger bounds before the tween is applied? Relevant code: useEffect(() => { const { current: element } = el; const parallax = gsap.fromTo(element, { translateY: `${amount}vh` }, { translateY: `-${amount}vh` }) ScrollTrigger.create({ trigger: element, start: "top bottom", end: "bottom top", animation: parallax, scrub: 0.3, markers: true }) }, []) 1 Link to comment Share on other sites More sharing options...
Cassie Posted May 19, 2022 Share Posted May 19, 2022 Hey there! Please can you put together a minimal demo for us. It's very hard for us to recommend a good approach without seeing the whole picture. I imagine the answer will be to add a containing div and animate the element inside though. Link to comment Share on other sites More sharing options...
Cassie Posted May 19, 2022 Share Posted May 19, 2022 Also no need for it to be a whole React demo if that will take longer. Just some divs and the GSAP code would be great! Thank you. Link to comment Share on other sites More sharing options...
SteveS Posted May 19, 2022 Author Share Posted May 19, 2022 I'll put one together shortly. That being said I tried the method you are suggested before making the post, the issue being that I'm not aware of a way to have an element ignore its parent. For example, if you want the element to be a flex child, adding a container element can interfere with how that child sits in its higher container. Link to comment Share on other sites More sharing options...
SteveS Posted May 19, 2022 Author Share Posted May 19, 2022 Here is a CSB showing the setup. The only issue is that the start and end positions of each are based on the from position rather than the elements unanimated position.https://codesandbox.io/s/priceless-mirzakhani-17pdtd?file=/src/App.js Link to comment Share on other sites More sharing options...
GreenSock Posted May 20, 2022 Share Posted May 20, 2022 If I understand your question correctly, yes, you're animating the trigger element which would affect the start/end positions. If you don't want that, you can either use a wrapper element - animate the inner element and use the wrapper as the trigger -OR- you can adjust your start/end values according to however far you're moving the trigger. Link to comment Share on other sites More sharing options...
SteveS Posted May 20, 2022 Author Share Posted May 20, 2022 I just want the scrollTrigger to use the elements untweened position values. I've managed to make a janky way of doing it by applying the scrollTrigger to an empty timeline, and then in the next useEffect I add the actual tweens. It works, but it would be much nicer if there were a way to target the elements before the tweens are put on them. Doesn't seem like that's the case though. Link to comment Share on other sites More sharing options...
GreenSock Posted May 20, 2022 Share Posted May 20, 2022 Right, I gave you two ways to do that Link to comment Share on other sites More sharing options...
SteveS Posted May 20, 2022 Author Share Posted May 20, 2022 Well, the caveat being not creating any wrapper elements, and targeting parents with offsets might totally work, though it's a bit more complicated. Link to comment Share on other sites More sharing options...
Solution Cassie Posted May 20, 2022 Solution Share Posted May 20, 2022 const parallax = gsap.fromTo( element, { translateY: `${amount}vh` }, { translateY: `-${amount}vh` } ); ScrollTrigger.create({ trigger: element, start: `top-=${amount} bottom`, end: `bottom-=${amount} top`, animation: parallax, scrub: 0.3, markers: true }); Adjusting your start/end values is probably what you're after? Link to comment Share on other sites More sharing options...
SteveS Posted May 20, 2022 Author Share Posted May 20, 2022 That actually might work, but the amount is in VH. Is that a supported relative transforms on the top and bottom? Link to comment Share on other sites More sharing options...
GreenSock Posted May 20, 2022 Share Posted May 20, 2022 8 minutes ago, SteveS said: That actually might work, but the amount is in VH. Is that a supported relative transforms on the top and bottom? No, you'd need to convert that to px. ScrollTrigger.create({ trigger: element, start: () => `top-=${amount * window.innerHeight / 100} bottom`, end: () => `bottom-=${amount * window.innerHeight / 100} top`, animation: parallax, scrub: 0.3, markers: true }); 2 Link to comment Share on other sites More sharing options...
SteveS Posted May 20, 2022 Author Share Posted May 20, 2022 This works in preliminary tests! Great! Working with scrollTrigger takes some getting used to, but translating the start and end by the translation amount totally makes sense. It's still not as ideal as getting to initial position to begin with, but it is certainly better than the solution I came up with. Thanks! Link to comment Share on other sites More sharing options...
SteveS Posted May 20, 2022 Author Share Posted May 20, 2022 Further testing showed that relative start end in itself didn't fix the issue. For whatever reason, the fromTo tween would complete before the end trigger. My solution was to create a timeline and add a from tween and a to tween manually. After attaching the timeline to the scroller, it now works as expected. For this to work, the from and to tweens must manually be set to have an ease of "none" otherwise they get the default ease and do not work as intended. 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