Jump to content
GreenSock

gabriel.ortiz

How does infinite loop refreshing work?

Go to solution Solved by GreenSock,

Recommended Posts

HI! I always have to start off by saying how much I love Greensock. It changed my life (not joking).  So i've been working to adapt a typescript version of  the `horizontalLoop` method as described in the https://greensock.com/docs/v3/HelperFunctions#loop helper functions. I plan to use it in React. 

 

I have a working version of this in a codesandboxhttps://codesandbox.io/s/gsap-marquee-loop-494fwh?file=/src/App.tsx

Here is the marqueeLoop class: https://codesandbox.io/s/gsap-marquee-loop-494fwh?file=/src/lib/maequeeLoop.ts

 

If i may make a humble ask.. I was hoping someone could explain to me the rationale for the logic behind the refresh() method on the window window.resize event. I would really appreciate the opportunity to learn. Here's the code:

 

  /**
   * Recalculates the the widths of the timeline, calculates the offsets
   *
   * @param deep {boolean}
   */
  refresh(deep?: boolean) {
    // Take a snapshot of the tl progress
    const progress = this.tl.progress();
    // Reset the tl to the beginning
    this.tl.progress(0, true);
    // repopulate the widths of the elements
    this.populateWidths();
    // rebuilds the timelines
    deep && this.populateTimeline();
    // populate the offsets between the timelines
    this.populateOffsets();

    deep && this.draggable?.[0]
       ? this.tl.time(this.times[this.curIndex], true)
       : this.tl.progress(progress, true);
  }

So my questions are:

  1. Why do we take a snapshot of here const progress = this.tl.progress();
  2. Why do we reset the tl progress to 0? this.tl.progress(0, true); Is this intended to pause the timeline while we recalculate?
  3. What is the rationale for either using the tl.time or thetl.progress based on Draggable? I don't understand the difference between these.

 

Likewise, in the `Draggable proxy`,

  1.  InDraggable.onPressInit, we are killing the tweens gsap,killTweensOf(self.tl). Why are we killing the tween? 
  2. Why are we also setting the proxy values here? gsap.set(self.proxy, {x:startProgress / -ratio} ) ?
  3. Also why does `Draggable` return an array?

 

    this.draggable = Draggable.create(this.proxy, {
      trigger: this.container,
      type: "x",
      onPressInit: () => {
        // Kills all the tweens actively in play
        gsap.killTweensOf(self.tl);
        // Take a snapshot of the tween progress
        startProgress = self.tl.progress();
        // Recalculate the tl spacing and width
        self.refresh();

        // Offset how much drag happens
        ratio = 1 / self.totalWidth;
        
        gsap.set(self.proxy, { x: startProgress / -ratio });
      },
      onDrag: function () {
        self.tl.progress(
          progressWrap(startProgress + (this.startX - this.x) * ratio),
        );
      },
      onThrowUpdate: function () {
        self.tl.progress(
          progressWrap(startProgress + (this.startX - this.x) * ratio),
        );
      },
      inertia: false,
      onRelease: syncIndex,
      onThrowComplete: syncIndex,
    });

 

I hope it's not too much to ask - but i would love to understand how this all works. Thanks so much!

  • Thanks 1
Link to comment
Share on other sites

  • Solution
6 hours ago, gabriel.ortiz said:
  • Why do we take a snapshot of here const progress = this.tl.progress();

So that we can return it to that progress when we're done doing all the measuring. Otherwise, when you resize it would appear to jump since we set progress to 0 (rewind).

 

6 hours ago, gabriel.ortiz said:
  • Why do we reset the tl progress to 0? this.tl.progress(0, true); Is this intended to pause the timeline while we recalculate?

Because we want to measure things in their natural/starting state, not after our timeline has moved things around, wrapped them, etc. Think of it like we're rewinding to the start in order to do the measurements correctly on that state.

 

6 hours ago, gabriel.ortiz said:
  1. What is the rationale for either using the tl.time or the tl.progress based on Draggable? I don't understand the difference between these.

If it's hooked up to a Draggable instance, it must synchronize with that. 

 

6 hours ago, gabriel.ortiz said:
  •  InDraggable.onPressInit, we are killing the tweens gsap,killTweensOf(self.tl). Why are we killing the tween? 

If you flick/throw the content and it's in the middle of an inertia tween of the timeline's progress, we want that to immediately stop when we press down. It'd be super weird if you clicked while it was moving...and it just kept on moving from under your mouse/touch. 

 

6 hours ago, gabriel.ortiz said:
  • Why are we also setting the proxy values here? gsap.set(self.proxy, {x:startProgress / -ratio} ) ?

That's the thing that's being dragged (though it's invisible - we're just using it for events and to grab its x value), so we want to align it to wherever the timeline's progress would dictate. Remember, we may have shot the progress value forward/backward with inertia (and there's no point in also doing that to the proxy...it's invisible). It only needs to be synced while we're dragging. 

 

6 hours ago, gabriel.ortiz said:
  1. Also why does `Draggable` return an array?

Because you can make a bunch of things Draggable with one call, like imagine you have 10 elements with a "box" class applied...

Draggable.create(".box", {...})

Will return an Array of 10 Draggable instances. Each one could be dragged to different positions, so it wouldn't make any sense to try to manage everything in one Draggable instance (what would its "x" and "y" properties be?) 

 

6 hours ago, gabriel.ortiz said:

I always have to start off by saying how much I love Greensock. It changed my life (not joking). 

Very glad to hear it. Thanks for the kind words.

 

I hope this helped. We don't normally provide walk-throughs of the code but I had a little time and wanted to provide some assistance. Please just do me a favor and avoid posting the code in a repo without attribution.

 

Happy tweening! 👍

Link to comment
Share on other sites

@GreenSock I appreciate so much you making an exception to explain these rationales. This is really invaluable because I can leverage these strategies in the future. I of course will attribute this forum and the original horizontalLoop in my work. I really do appreciate your time.. thanks!

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Happy to help. 

 

Maybe consider joining Club GreenSock - that'd get you InertiaPlugin which could make the dragging functionality a lot more cool in the helper function. No pressure :) 

  • Like 1
Link to comment
Share on other sites

20 hours ago, GreenSock said:

Happy to help. 

 

Maybe consider joining Club GreenSock - that'd get you InertiaPlugin which could make the dragging functionality a lot more cool in the helper function. No pressure :) 

haha i'm talking to my manager about that RIGHT NOW!

At a minimum can I buy yall a cup of coffee or a beer somehow?

Link to comment
Share on other sites

1 hour ago, gabriel.ortiz said:

haha i'm talking to my manager about that RIGHT NOW!

🥳

 

1 hour ago, gabriel.ortiz said:

At a minimum can I buy yall a cup of coffee or a beer somehow?

Nope. Very kind of you, but we don't want anyone feeling indebted or obligated. Our entire business model is built on good will and the honor system. Club GreenSock is what makes this all possible (plus the generous and talented moderators who pitch in here). We trust that if we keep building the best tools we can and serving our customer base well, the market will naturally respond and reward those efforts in the long run. Get a Club GreenSock membership if and when you decide it's prudent. 

 

Good luck with the conversation with your manager. In case it helps:

 

And again, there's no pressure whatsoever to join the Club. Hopefully it becomes clear that a membership would pay for itself in a matter of days or weeks and then make you more profitable with all those animation superpowers. ;) If that's not the case for you, no worries.  

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

This topic was incredibly useful for me! I've been struggling so hard to get a marquee to work in React. 

  • Like 2
Link to comment
Share on other sites

Glad to hear - and nice to have a chat over in discord. Hope to see you back in here when you're a GSAP & React expert 😉

  • Thanks 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×