Jump to content
GreenSock

clf

Avoid creating timelines on click

Go to solution Solved by GreenSock,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello again.

 

I'v got another stupid question and very ashamed to ask it. I want to create animation exactly like in my attached codepen, but without creating new timeline at every click. I tried something like this

var TL1 = new TimelineLite({paused:true});
TL1
.to($("#box"), 2, {y: 200,ease: Bounce.easeOut})
.call(function (newText) {$("#box").text(newText);},["Up"], this, 0.2); 


var TL2 = new TimelineLite({paused:true});
TL2
.to($("#box"), 2, {y: 0,ease: Cubic.easeInOut})
.call(function (newText) {$("#box").text(newText);},["Down"], this, 0.5);

and then 

$("#box")
.click(function () {
  $(this).toggleClass("register");
  if ($(this).hasClass("register"))
    {
     TL1.restart();
    }
  else
    {
      TL2.restart();
    }
}); 

but it didn't work.

 

Of course in that situation the animation begins from the start of timeline 1 or 2, so if i click on the box before the timeline ends it's jumps to the beginning.  

 

How can i avoid creating timelines on every click event?

 

Thanks.

See the Pen dXazqA by clf (@clf) on CodePen

Link to comment
Share on other sites

  • Solution

I noticed a few problems:

  1. Since you've got two timelines that are BOTH controlling the same properties of the same element, you need to be careful about conflicts. For example, imagine TL1 is running and then the user clicks the button...if you start TL2, now you've got two animations trying to control #box.y to completely different ends. Therefore, you should TL1.pause() before you TL2.restart() (and vice-versa). 
  2. The first time a tween/timeline runs, it'll record the starting/ending values but in your case, you're trying to set something up that's completely dynamic. The simplest way to accommodate this is by calling invalidate() on the timeline/tween which flushes any recorded start/end values and re-reads them from the current values. 

With that in mind, here's how I simplified the code a bit and made it work the way I think you intended:

var TL1 = new TimelineLite({paused:true});
TL1.to("#box", 2, {y: 200,ease: Bounce.easeOut})
   .call(changeText, ["Up"], this, 0.2);

var TL2 = new TimelineLite({paused:true});
TL2.to("#box", 2, {y: 0,ease: Cubic.easeInOut})
   .call(changeText, ["Down"], this, 0.5);

$("#box").click(function () {
  $(this).toggleClass("register");
  if ($(this).hasClass("register")) {
      TL2.pause();
      TL1.invalidate().restart();  
    } else {
      TL1.pause();
      TL2.invalidate().restart();
    }
});

function changeText(newText) {
  $("#box").text(newText);
}
Better?
  • Like 4
Link to comment
Share on other sites

Big thanks. I almost understand 1 and 2nd items, but can you explain why my first example ( where im creating a "new Timelines" on every click) works? Should i avoid such constructions and always create one instance of timeline for one animation sequence? In this example

See the Pen oLmGPb?editors=1111 by clf (@clf) on CodePen

i can't see any collisions, or memory leaks, or performance issues but the dark side i sense in code =)

Link to comment
Share on other sites

Yeah, it's totally fine to create new timelines on each click. That's not "bad"; it won't cause memory leaks or poor performance. The timelines will automatically get garbage collected once they're done (well, unless you maintain references to them of course). It's only slightly more efficient to reuse the same timeline and just invalidate() it on each use. Again, the whole point there is that in your particular case you're trying to make things totally dynamic so that the starting values could pick up from anywhere. That's why creating new timelines gave you that effect - you were telling it to just start from wherever the values were at that time. If, however, you reuse timelines that have already instantiated and locked in their starting/ending values, when you restart() they'll jump back to the original starting values (instead of using whatever the current values are). The other benefit of just creating new timelines each time is that you don't have to worry about pausing the old one, as it'll just get overwritten automatically by the new one(s). 

 

Hopefully that clears things up. Either technique is valid. 

 

Happy tweening!

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