SWALKER Posted March 26 Share Posted March 26 I am going slightly mad. I have spent nearly a week trying to get this to work and I can't understand what's going on. I have been trying to some basic pinning with a clip mask and I just can't get it to behave responsibly. Annoyingly on that codepen URL it's actually okay, but on my website, it's not, which I realise makes things difficult. I have done another codepen with ALL my GSAP code (rather than it reduced to the animation in question which is linked above) and that one glitches more so there must be some offending code elsewhere, but I can't work out what, as it all seems fine to me. See the Pen gOyxppY by shereewalker (@shereewalker) on CodePen I am removing each piece of extra JS to see if I can work it out, but so far nothing is working. I am basically just trying to refresh the calculations on window resize for that animation - and actually for all of them Any help would be amazing as I am at my wits end! Thanks! See the Pen KKYvKRJ by shereewalker (@shereewalker) on CodePen Link to comment Share on other sites More sharing options...
Rodrigo Posted March 26 Share Posted March 26 Hi, Sorry to hear about the issues but I'm afraid I can't replicate the problem in neither demo, I resized both of them quite a few times and they keep working in the same way. Unfortunately in your first demo there is too much code (over 500 lines between CSS and JS) and we don't have the time resources to comb through all that. Also in the same first demo you're not including jquery and there are a lot of warnings that point to elements not being found by GSAP on the DOM, so clearly there are quite a few elements that are missing. In your second demo I saw this: // Function to refresh ScrollTrigger on resize function refreshScrollTrigger() { ScrollTrigger.refresh(); } // Event listener for window resize window.addEventListener("resize", refreshScrollTrigger); // Initialize ScrollTrigger ScrollTrigger.create(scrollTriggerConfig); // Initial setup refreshScrollTrigger(); There is no need to manually call ScrollTrigger.refresh(), especially if nothing in the ScrollTrigger instances depends on something changing after some time when the user resizes the screen. ScrollTrigger calls the refresh method automatically when the screen is resized and does it with a debounce mechanism for better performance. You might need to call that if some content is added/removed asynchronously and you need for ScrollTrigger to run it's calculations again, so except for the create() method everything else in that code block is not really necessary IMHO. As for the issue please be more specific about how it can be replicated and what exactly is happening or not happening. Finally you might want to check GSAP MatchMedia: https://gsap.com/docs/v3/GSAP/gsap.matchMedia() Happy Tweening! Link to comment Share on other sites More sharing options...
SWALKER Posted March 26 Author Share Posted March 26 HI there, Thanks for your reply. It can be replicated but it has to be a very drastic move, from small to big which I should have pointed out and generally only works in the second demo. It's really bad on the live site but I don't suppose there's any point in posting a link as there would be too much to wade through. Weirdly when I remove those lines you suggested, everything breaks. Can you suggest a simplified way to correctly pin that section? Thanks again Link to comment Share on other sites More sharing options...
SWALKER Posted March 26 Author Share Posted March 26 So i have just tried switching it to the below and removing the code you suggested: gsap.to(".row._1", { scrollTrigger: { trigger: ".row._1", start: "top top", scrub: true, pin: true, pinSpacing: false, invalidateOnRefresh: true }, }); And actually it works better, I'm not sure why I didn't have it like this before. I think it was reconstructed to assist with the refresh. I'll keep my eye on it, but it's definitely better. Thanks so much for your help Link to comment Share on other sites More sharing options...
SWALKER Posted March 26 Author Share Posted March 26 Actually one other question if you don't mind, if Scrolltrigger automatically refreshes, what purpose does ' invalidateOnRefresh: true' serve? Thanks again! Link to comment Share on other sites More sharing options...
Rodrigo Posted March 26 Share Posted March 26 Hi, I just forked your second demo, removed all the code I suggested to remove and everything seems to keep working as expected after several resizes, I tried to resize as fast as I could, which is worth noticing that 99.99% of normal users don't do, just developers with an itch for unrealistic testing do that (nothing personal against neither you or other developers, just a personal opinion based on working on this area for over 13 years): See the Pen eYoEpPO by GreenSock (@GreenSock) on CodePen 19 minutes ago, SWALKER said: Actually one other question if you don't mind, if Scrolltrigger automatically refreshes, what purpose does ' invalidateOnRefresh: true' serve? From the ScrollTrigger docs: invalidateOnRefresh Boolean - If true, the animation associated with the ScrollTrigger will have its invalidate() method called whenever a refresh() occurs (typically on resize). This flushes out any internally-recorded starting values. https://gsap.com/docs/v3/GSAP/Tween/invalidate() Sometimes you need GSAP to record again the initial values of the element being animated and dump the previous ones, because the new screen size (since this is triggered on ScrollTrigger's refresh method) could change those values and GSAP instances are mostly read-only, so GSAP only records the initial and final values once and then iterates between them over a specific amount of time, one of the many micro optimizations that makes GSAP super performant. Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
SWALKER Posted March 26 Author Share Posted March 26 Hi there, On the live site. You don’t have to resize quickly, it’s considerably worse. Enough that I think a simple device orientation change would cause it. A quick resize was the only way I could get the demo to do it. It’s working a lot better now. It’s not perfect but it’s better. I read the docs for invalidation on refresh but it sounded like the same thing to me, which is why I asked. Thanks for that extra info. So much to learn! I will take a look at your fork tomorrow. Thanks again for your help, much appreciated Link to comment Share on other sites More sharing options...
Cassie Posted March 27 Share Posted March 27 Here's a simple code example of invalidateOnRefresh gsap.to(".el", { xPercent: () => window.innerWidth / 2, // here's a functional value that will update if the window size changes, (it will 'invalidate' on 'refresh') rotation: window.innerWidth / 2, // this value won't update scrollTrigger: { invalidateOnRefresh: true ... } }) 2 Link to comment Share on other sites More sharing options...
SWALKER Posted April 2 Author Share Posted April 2 Ugh, so after FINALLY thinking this was working, it now ONLY works with markers on. Without them, the animation is all over the place and all the other ones are jumpy. With them on, it's perfect. It makes no sense to me! I can't seem to do a demo to replicate it which I know leaves me in a situation This URL is here, maybe something will jump out https://staging-chfp.shereewalker.com/ At the moment, I have it working by having markers:true and the hiding them with CSS VERY hacky but I only have a a few days until launch Link to comment Share on other sites More sharing options...
Rodrigo Posted April 2 Share Posted April 2 Hi, Sorry about the issues but yeah, without a demo that clearly illustrates the problem there is not a lot we can do ?♂️ The only thing I can think of is that somehow the markers are pushing the height of the document element so everything works as expected. You should review your setup in order to see if something in your HTML/CSS could be causing something that the markers are actually fixing, which would be quite weird TBH. Another option is that something else (like another JS package or CSS library) is interfering with this and causing the problem. Try removing some of them one by one and see if that fixes anything. As I was about to submit this I checked your site again and opened devtools and I noticed that you're using wordpress and that your body element has scroll-behavior: smooth, that could be a source of problems (linke 92): https://staging-chfp.shereewalker.com/wp-content/themes/CHFP/style.css?ver=1.0 Try overriding that in a custom CSS that is loaded after the theme's styles in order to see if it helps. Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
SWALKER Posted April 2 Author Share Posted April 2 Hey there, Yeah I know that lack of demo doesn't help sorry - I do actually have one, but I can't replicate the issue. I searched other forums and I'm not the first person who has experienced this so i thought maybe there was a generic answer. Most other forums imply it has to do with a lack of height on the page, which I don't have - there is more than enough top and bottom. I have a gross solution for now which is that I have turned markers on, and then hid them with CSS. It's not a long term solution (at the moment!) but it will do until I can work it out. I have tried stripping out all my other css and JS but no joy. Oddly if I move the section with the pinning, its okay - it's almost like the combination of the pinning animation AND the section above which has VW and VH calculations is too much for it to pinpoint the starting and ending? It's weird. And again, if I add markers - it's fine. I will try removing that scroll behaviour - and see if it makes a difference. - thanks very much for that suggestion. Link to comment Share on other sites More sharing options...
SWALKER Posted April 18 Author Share Posted April 18 So I THINK i have worked this out - after a huge amount of time! I noticed that the section worked fine, a long as there was NO other blocks on the page. But no single block seemed to be the issue - it was ANY block on the page. The only common denominator they had was the padding (which I ruled out) and they each had a heading - which was, believe it or not, the issue. It was cause by the css transition: all .3s ease-in-out; Which had been applied, to every heading. When resizing quickly (for example on ipad orientation change), scroll trigger calculates WHILE the headings are still in the process of resizing - thus, throwing off the calcultaions. Fingers crossed this is it, but it appears to have fixed the issue Edit - false alarm..... it has not Link to comment Share on other sites More sharing options...
Rodrigo Posted April 18 Share Posted April 18 Hi, Sorry about the issues, but as mentioned without a demo that clearly reproduces the problem there is not a lot we can do. The only advice I can give you is to keep looking into anything that could change the height of the document when resizing, maybe images with src set, maybe different screen sizes will use different images with different heights, that could load the image after the ScrollTrigger instance is created. Happy Tweening! Link to comment Share on other sites More sharing options...
SWALKER Posted April 18 Author Share Posted April 18 Hi there I have looked and I have even removed almost everything off the page except a basic text block. I use src set but the images use object-fit so their containers dont change. Some elements on the page are based on VH but I can't change this. I know that without a broken demo it's near impossible but are you able to just tell me how to correctly kill an animation on resize? Sorry i have confused things by opening another thread. I thought maybe this was too old now Link to comment Share on other sites More sharing options...
GreenSock Posted April 19 Share Posted April 19 4 hours ago, SWALKER said: tell me how to correctly kill an animation on resize? Again, it's tough to advise without seeing a minimal demo, but I guess the most generic answer I can give would be: "call kill() on that animation from inside a 'resize' event handler". But if you want a more targeted answer for your scenario, please provide a minimal demo that clearly illustrates the problem and we'd be happy to take a peek. Link to comment Share on other sites More sharing options...
SWALKER Posted April 19 Author Share Posted April 19 Hi there, I just can't get the demo to replicate it sorry. I have done this - but it's not perfect. Would you recommed a better way to "call kill() on that animation from inside a 'resize' event handler". / Function to invalidate and remake specific animations function invalidateAndRemakeAnimations() { // Kill the first animation ScrollTrigger.getAll().forEach(trigger => { if (trigger.vars.trigger === ".row._1") { trigger.kill(); } }); // Remake the first animation gsap.to(".row._1", { scrollTrigger: { trigger: ".row._1", start: "top top", scrub: true, pin: true, pinSpacing: false, invalidateOnRefresh: true, markers: true } }); // Kill the second animation ScrollTrigger.getAll().forEach(trigger => { if (trigger.vars.trigger === ".row._3") { trigger.kill(); } }); // Remake the second animation gsap.to("h2.text", { scrollTrigger: { trigger: ".row._3", start: "top top", scrub: true, invalidateOnRefresh: true }, position: "relative" }); } // Initial application of animations invalidateAndRemakeAnimations(); // Listen for orientation change event window.addEventListener("orientationchange", function() { // When orientation changes, invalidate and remake specific animations invalidateAndRemakeAnimations(); }); Link to comment Share on other sites More sharing options...
GreenSock Posted April 19 Share Posted April 19 I assume maybe you mean something like this?: let tween1, tween2; function invalidateAndRemakeAnimations() { // Kill existing animations tween1 && tween1.revert(); tween2 && tween2.revert(); // Remake the first animation tween1 = gsap.to(".row._1", { scrollTrigger: { trigger: ".row._1", start: "top top", scrub: true, pin: true, pinSpacing: false, invalidateOnRefresh: true, markers: true } }); // Remake the second animation tween2 = gsap.to("h2.text", { scrollTrigger: { trigger: ".row._3", start: "top top", scrub: true, invalidateOnRefresh: true }, position: "relative" }); } Link to comment Share on other sites More sharing options...
SWALKER Posted April 19 Author Share Posted April 19 I've actually just rebuilt the whole thing Without pinning but the markers still off on orientation change! To apply the above to the new animations, is this correct because it does not work, i think maybe I have modified it incorrectly let tween1, tween2, tween3 ; function invalidateAndRemakeAnimations() { // Kill existing animations tween1 && tween1.revert(); tween2 && tween2.revert(); tween3 && tween3.revert(); // Remake the first animation tween1 = gsap.to(".fixed-wrap", { scrollTrigger: { trigger: ".initial-row", start: "top top", scrub: true, invalidateOnRefresh: true, markers: true }, position:'fixed' }); // Remake the second animation tween2 = gsap.to(".last-text .text-holder .text", { scrollTrigger: { trigger: ".last-text", start: "top top", scrub: true, invalidateOnRefresh: true, markers: true }, position:'relative' }); tween3 = gsap.to(".fixed-wrap", { scrollTrigger: { trigger: ".last-text", start: "top top", scrub: true, invalidateOnRefresh: true, markers: true }, position:'relative' }); } Alternatively, do you know how to use function based start/end values? The docs just say this as an example , but I don't really know what this means end: () => `+=${elem.offsetHeight}` // will be updated Thank you! Link to comment Share on other sites More sharing options...
Rodrigo Posted April 19 Share Posted April 19 Function based values mean that when the ScrollTrigger instance is refreshed that end value will be whatever number/string that function returns. If oyu're doing some sort of calculation whose result might change that calculation will be run again. In the particular snippet you added the end point is based on the height of an element, if a screen resize changes the height of that element then the end point will be recalculated as well. Hopefully this clear things up. Finally it seems that you have created two different threads for the same issue, please let's keep the discussion in just one thread. That will make easier to follow and focus our efforts, thanks! Happy Tweening! 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