Jump to content
Search Community

Vilas

Premium
  • Posts

    9
  • Joined

  • Last visited

Posts posted by Vilas

  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?

  2. 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

  3. 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

     

     

  4. 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 });
                    }
                }
            }, '<');
  5. Thank you guys! I have a rather long page with 3-4 sections in between which are dynamic and slow.

    Simply using the .sort() method didn't work

     

    But using the verticalSort() helper function you suggested did the trick.

    I just had to include ScrollTrigger.refresh() after the sorting to make it work properly:

     

    function verticalSort() {
        let scroll = window.scrollY;
        ScrollTrigger.getAll().forEach(t => t._sortY = t.trigger ? scroll + t.trigger.getBoundingClientRect().top : t.start + window.innerHeight);
        ScrollTrigger.sort((a, b) => a._sortY - b._sortY);
        ScrollTrigger.refresh();
    }
    • Like 1
  6. Hi guys,

     

    I created this super basic codepen file to illustrate the issue.

    So the problem is that the middle section is waiting for some data before initializing the scrollTrigger+pinning.

    Once the data is loaded and the pinning happens, it throws off the position of all the scrollTriggers below it.

     

    Running scrollTrigger.refresh() doesn't seem to do anything in this case.

     

    How can i re-calculate the position of all the scroll triggers once the data finishes loading?

     

    See the Pen MWRxXZW by omikron1989 (@omikron1989) on CodePen

  7. On 4/15/2024 at 11:43 PM, Rodrigo said:

    Hi @Vilas and welcome to the GSAP Forums!

     

    You're using the invalidate method AFTER restarting the timeline, it has to be BEFORE:

    const runAnimation = (currentColorName) => {
      currentColor = currentColorName;
      tl.invalidate();
      tl.restart();
    };

     

    Another option is to use the call method:

    https://gsap.com/docs/v3/GSAP/Timeline/call()

     

    const tweenFill = () => {
      gsap.to(circles, {
        stagger: { each: 0.05 },
        ease: "none",
        fill: function () {
          return `#${currentColor}`;
        }
      });
    };
    
    tl.call(tweenFill);
    
    tl.to(
      circles,
      {
        stagger: { each: 0.05, repeat: 1, yoyo: true },
        scale: 1.05,
        ease: "sine.inOut",
        transformOrigin: "center center"
      },
      "<"
    );

    Here is a fork of your codepen:

     

     

     

    Hopefully this helps

    Happy Tweening!

    This is awesome! Thank you so much! 

     

    So using the .call function injects the callback into the timeline and runs is every time the animation plays? but with updated parameters? 
    That seems super useful!

     

     

  8. Hi guys, 

     

    I have a gsap timeline which animates an svg circle. (Scale and color).

     

    What I'm trying to achieve is to pass a dynamic color when clicking different buttons, for example:

     

        buttonA.addEventListener('click', (e)=>{runAnimation(DYNAMIC_VALUE)});

     

     

    and then use that value here:
        tl.to(circles, {
            stagger:{ each: 0.05},
            ease: "none",
            fill: `#${DYNAMIC_VALUE}` 
        })

     

    It seems that the dynamic value is always using the initial value but can't be changed later. 
    Any idea on how to bypass this issue?

     

    Edit: seems that using a function + tl.invalidate() works, however, spam clicking the button seems to break the animation. Any ideas?

     

    Thank you in advance!

    See the Pen zYXJYPY by omikron1989 (@omikron1989) on CodePen

×
×
  • Create New...