Vilas Posted May 1 Share Posted May 1 I have 3 blocks of text which appear as you scroll and I am fading in each one depending on where in the timeline the progress is. I am wondering if there is any more efficient way to do this as the code below looks very redundant tl.to(blocks,{ ease: 'power1.inOut', duration: 100, onUpdate: function () { const progress = tl.progress(); if (progress > 0 && progress <= 0.5) { gsap.killTweensOf([block2, block3]); // Cancel ongoing animations on block2 and block3 gsap.to(block1, { opacity: 1, y: 0, duration: opacityDuration }); gsap.set(block2, { opacity: 0, y: 15, }); gsap.set(block3, { opacity: 0, y: 15, }); } else if (progress > 0.5 && progress <= 0.7) { gsap.killTweensOf([block1, block3]); // Cancel ongoing animations on block1 and block3 gsap.set(block1, { opacity: 0, y: 15, }); gsap.to(block2, { opacity: 1, y: 0, duration: opacityDuration }); gsap.set(block3, { opacity: 0, y: 15, }); } else if (progress > 0.7 && progress <= 1) { gsap.killTweensOf([block1, block2]); // Cancel ongoing animations on block1 and block2 gsap.set(block1, { opacity: 0, y: 15, }); gsap.set(block2, { opacity: 0, y: 15 }); gsap.to(block3, { opacity: 1, y: 0, duration: opacityDuration }); } } }, '<'); Link to comment Share on other sites More sharing options...
GSAP Helper Posted May 1 Share Posted May 1 Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer. See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo: Using a framework/library like React, Vue, Next, etc.? CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: React (please read this article!) Next Svelte Sveltekit Vue Nuxt Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. ✅ Link to comment Share on other sites More sharing options...
Rodrigo Posted May 1 Share Posted May 1 Hi, Besides echoing the need for a minimal demo, I'd advice you to not use all that convoluted conditional logic, keep in mind that this block: if (progress > 0 && progress <= 0.5) { gsap.killTweensOf([block2, block3]); // Cancel ongoing animations on block2 and block3 gsap.to(block1, { opacity: 1, y: 0, duration: opacityDuration }); gsap.set(block2, { opacity: 0, y: 15, }); gsap.set(block3, { opacity: 0, y: 15, }); } Will run 60 times per second while the progress value is less than 0.50000001, that means you'll create a new to() instance that will override a previously created one and you will be creating set() instances that are no longer needed. You should use the position parameter to add your instances at specific points of your timelne: https://gsap.com/resources/position-parameter/ If your instance is 10 seconds, then you can do something like this: const tl = gsap.timeline(); tl .to(blocks, { duration: 10 }, 0) .to(block1, { duration: opacityDuration, opacity: 1, y: 0, }, 0) .set(block2, { opacity: 0, y: 15, }, 0) .set(block3, { opacity: 0, y: 15, }, 0) .to(blocks, { duration: 10 }, 0.5) .to(block1, { duration: opacityDuration, opacity: 1, y: 0, }, 0) .set(block2, { opacity: 0, y: 15, }, 0.5) .set(block3, { opacity: 0, y: 15, }, 0.5) Of course ideally you'd have to find a dynamic way to achieve that, maybe using a combination of the position parameter and the call() method: https://gsap.com/docs/v3/GSAP/Timeline/call() Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
Vilas Posted May 1 Author Share Posted May 1 1 hour ago, Rodrigo said: Hi, Besides echoing the need for a minimal demo, I'd advice you to not use all that convoluted conditional logic, keep in mind that this block: if (progress > 0 && progress <= 0.5) { gsap.killTweensOf([block2, block3]); // Cancel ongoing animations on block2 and block3 gsap.to(block1, { opacity: 1, y: 0, duration: opacityDuration }); gsap.set(block2, { opacity: 0, y: 15, }); gsap.set(block3, { opacity: 0, y: 15, }); } Will run 60 times per second while the progress value is less than 0.50000001, that means you'll create a new to() instance that will override a previously created one and you will be creating set() instances that are no longer needed. You should use the position parameter to add your instances at specific points of your timelne: https://gsap.com/resources/position-parameter/ If your instance is 10 seconds, then you can do something like this: const tl = gsap.timeline(); tl .to(blocks, { duration: 10 }, 0) .to(block1, { duration: opacityDuration, opacity: 1, y: 0, }, 0) .set(block2, { opacity: 0, y: 15, }, 0) .set(block3, { opacity: 0, y: 15, }, 0) .to(blocks, { duration: 10 }, 0.5) .to(block1, { duration: opacityDuration, opacity: 1, y: 0, }, 0) .set(block2, { opacity: 0, y: 15, }, 0.5) .set(block3, { opacity: 0, y: 15, }, 0.5) Of course ideally you'd have to find a dynamic way to achieve that, maybe using a combination of the position parameter and the call() method: https://gsap.com/docs/v3/GSAP/Timeline/call() Hopefully this helps. Happy Tweening! Hi Rodrigo, I tried to illustrate it in the following codepen but I think i didn't get it quite right. So the idea is that there is a pinned container which is connected to a scroll trigger and at precise moments in the timeline, for example when the progress is 0.3 then the block 1 should appear. If the progress goes to 0.74 then block 2 should appear. All 3 blocks are in the same position just only 1 visible at a time. See the Pen abxrRYe?editors=1111 by Valentin-Ilas (@Valentin-Ilas) on CodePen Link to comment Share on other sites More sharing options...
Rodrigo Posted May 1 Share Posted May 1 10 minutes ago, Vilas said: for example when the progress is 0.3 then the block 1 should appear. If the progress goes to 0.74 then block 2 should appear. All 3 blocks are in the same position just only 1 visible at a time. That is exactly what the position parameter can do. Another way is to keep the logic you have now, but find a way to run it just once and not everytime the GSAP instance updates, that's too wasteful. Happy Tweening! Link to comment Share on other sites More sharing options...
Vilas Posted May 1 Author Share Posted May 1 2 hours ago, Rodrigo said: That is exactly what the position parameter can do. Another way is to keep the logic you have now, but find a way to run it just once and not everytime the GSAP instance updates, that's too wasteful. Happy Tweening! I've been trying to use the position parameter and I feel like I'm close but not quite there yet I noticed some interesting behaviour: if scrub is set to true, then the a duration seems to be needed. So i added duration: 100 which seems to work more as a percentage If i use the position parameter on each block, with values such as 20, 30 50 etc, they seem to trigger based on the percentage as well. Now what i can't seem to be able to do is to make the fade-in more animated instead of running it instantly and how to control the duration of the fade in. Please see the example below: See the Pen abxrRYe by Valentin-Ilas (@Valentin-Ilas) on CodePen Link to comment Share on other sites More sharing options...
Vilas Posted May 1 Author Share Posted May 1 3 hours ago, Rodrigo said: That is exactly what the position parameter can do. Another way is to keep the logic you have now, but find a way to run it just once and not everytime the GSAP instance updates, that's too wasteful. Happy Tweening! After more tinkering, i think i found a solution: See the Pen ZEZNVRX?editors=1111 by Valentin-Ilas (@Valentin-Ilas) on CodePen Basically I'm using tl.add() to run animations independently from the scrub on the parent container. Then i can specify for each one where during the progress it should run. Seems to work backwards too. But is this approach efficient? or do you see any performance issues? Link to comment Share on other sites More sharing options...
Solution Rodrigo Posted May 1 Solution Share Posted May 1 1 hour ago, Vilas said: But is this approach efficient? or do you see any performance issues? I doubt you'll run into performance problems with this TBH, since you have a rather small collection of elements. IMHO though this seems simpler to understand, follow and maintain: const blockElements = gsap.utils.toArray(".block"); const block1 = blocks.querySelector(".block-1"); const block2 = blocks.querySelector(".block-2"); const block3 = blocks.querySelector(".block-3"); const blockSettings = [ { element: block1, position: 30 }, { element: block2, position: 50 }, { element: block3, position: 60 } ]; blockSettings.forEach((b, i) => { const block = blockElements[i]; const otherBlocks = blockElements.filter((block, j) => i !== j); tl.add(() => { gsap.to(block, { opacity: 1, duration: 1, scale: 1 }); gsap.to(otherBlocks, { opacity: 0, duration: 1, scale: 1.2 }); }, b.position); }); You don't have to resort to that conditional block and anything that results in simpler and shorter code, is going to make more sense if you have to look at it in 6 months. Here is a fork of your demo: See the Pen oNORmKL by GreenSock (@GreenSock) on CodePen Is worth mentioning that using the add() to add an anonymous function is the same as using call(): const tl = gsap.timeline(); tl.add(() => {}, position); // Exactly the same tl.call(() => {}, [/*parameters*/], position); Hopefully this helps. Happy Tweening! 1 Link to comment Share on other sites More sharing options...
PointC Posted May 1 Share Posted May 1 I'd go even simpler with yoyo tweens and repeatDelay. Something like this. See the Pen 63a3e8ecfaf75286961b6e2ec36abed7 by PointC (@PointC) on CodePen Just my 2 cents. YMMV. Happy tweening. Just FYI - the original pen that I forked had tweens with a 0.1 → 1 second duration on a timeline that was 100 seconds long. With scrub set to true they were animating super fast because they were only a tiny fraction of the duration. .1% - 1%. 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