jfudman Posted June 21 Share Posted June 21 I am programmatically moving an element inside of a pinned trigger to the center of the viewport via scrolltrigger with timeline animations. It works, but values do not properly update on resize. I'm setting values with anonymous functions, i even read through this post... but I'm still stuck. What's worse is `invalidateOnRefresh` is breaking some values (see codepen). Finally, I have to refresh the tl.scrollTrigger in order to use the tl.scrollTrigger.start value. Does anyone know why? See the Pen poQEWKZ by jfudman (@jfudman) on CodePen Link to comment Share on other sites More sharing options...
Rodrigo Posted June 22 Share Posted June 22 Hi, I think the issue could be in the calculations you're doing for the Y value. Which raises the question of why you're doing that and if it's completely necessary. If the element is an ancestor of the element being pinned: Why animate it's Y value anyways? and Why you need the starting point of the ScrollTrigger instance which is based on the position of the top ancestor that is getting pinned? Unless I'm missing something it doesn't really make much sense to me. Also keep in mind that the values of getBoundingClientRect returns are based on the position of the element in the viewport, so if the element is not below or above the viewport this will return values based on that: const elRect = el.getBoundingClientRect(); https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect Maybe using offsetTop and offsetLeft of the parent element plus margins/paddings. IMHO you're overcomplicating this a bit, I forked your codepen and removed the Y value in your timelines and commented out a few things and I'm getting the same results with invalidateOnRefresh: true: See the Pen OJaRzGy by GreenSock (@GreenSock) on CodePen Finally another option would be to use the Flip Plugin: https://greensock.com/docs/v3/Plugins/Flip Maybe this example that combines ScrollTrigger and Flip with scrub can help: See the Pen bGxOjeP by GreenSock (@GreenSock) on CodePen Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
jfudman Posted June 22 Author Share Posted June 22 Thanks for the reply @Rodrigo. Here is a fork of your fork with some explanations as to why i need to determine the y value.Long story short: there will sometimes be content above or below the box. I use the Scrolltigger.start value in the calculation because the pinned element's start value will sometimes be different See the Pen ZEmpmRY by jfudman (@jfudman) on CodePen Link to comment Share on other sites More sharing options...
Cassie Posted June 22 Share Posted June 22 Heya! So I would definitely approach this using FLIP, have you checked out that demo that Rodrigo linked? It's great for layout stuff like this. Link to comment Share on other sites More sharing options...
jfudman Posted June 22 Author Share Posted June 22 Yeah the plugin looks awesome and I'll likely end up using it. Thank y'all for for the suggestion @Rodrigo and @Cassie! Although I still would like to know why my code doesn't work on resize because it theoretically should lol 1 Link to comment Share on other sites More sharing options...
Solution GreenSock Posted June 23 Solution Share Posted June 23 On 6/21/2023 at 4:13 PM, jfudman said: Finally, I have to refresh the tl.scrollTrigger in order to use the tl.scrollTrigger.start value. Does anyone know why? That's because timelines with a ScrollTrigger attached must WAIT to refresh until the timeline actually gets populated, thus it waits one tick (it can't know when you're done adding stuff - that's why it waits 1 tick). Otherwise, the timeline would have zero duration which makes scrubbing pretty weird, plus snapping to "labelsDirectional" couldn't work (no labels), etc. Individual tweens can refresh right away upon creation, but timelines have to wait. Of course you can manually call the .refresh() method when you're done populating it if you don't want it to wait a tick. The reason that invalidateOnRefresh: true was breaking things for you was due to the fact that you weren't calculating them in a way that includes the scroll position. When you DON'T have invalidateOnRefresh, it was just doing the calculations initially, when the page wasn't scrolled at all. But if you do invalidateOnRefresh, it invalidates on refresh and then the next time that animation renders, THAT Is when it calls the function-based values. So in your demo, that would be when the user scrolled enough to hit the ScrollTrigger start position, thus your getBoundingClientRect() wouldn't reflect y values inclusive of the scroll position. // bad y: elRect.height / 2 + elRect.y // good y: elRect.height / 2 + elRect.y + window.pageYOffset Is this what you were looking for?: See the Pen mdQOejX?editors=0010 by GreenSock (@GreenSock) on CodePen 2 Link to comment Share on other sites More sharing options...
jfudman Posted June 23 Author Share Posted June 23 HOLY SMOKES BATMAN! Thank you! 6 hours ago, GreenSock said: Individual tweens can refresh right away upon creation, but timelines have to wait. This is good to know – sounds like common sense in hindsight. I appreciate everyone's time here! 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