Jump to content
Search Community

how do I reset or reverse a tween?

bobdobbs test
Moderator Tag

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

In the following code, the first function works.

 

However, the second function throws an error.

tl = TweenMax ;

    $("#run").click(function(el) {
        var el = $(".box") ;
        tl.to( el , 2, { left: 10 } ) ;        
        console.debug( "done" );
    }) ;

    $("#reset").click(function (){
    tl.reverse() ;
    console.debug( "reverse done" );
    });

If I replace 'reverse()' with 'pause()' or 'reset()', I get similar looking errors:

Uncaught TypeError: Object function (t,e,s){i.call(this,t,e,s),this._cycle=0,this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._dirty=!0,this.render=r.prototype.render} has no method 'pause' 

I guess those methods aren't available to TimeLineMax. In which case, how do I do a reset or reverse?

Link to comment
Share on other sites

There are several problems:

  1. You used TweenMax instead of TimelineMax - I think you meant to use the latter. (right?)
  2. You're trying to call reverse() as if it's a static method of the TweenMax object. It's not. Remember, GSAP is a very object-oriented system, so you create TimelineMax instances and control those individually. reverse(), play(), seek(), pause(), and all of those kinds of methods are instance-based. You can create as many instances as you want. For example:
var tl_1 = new TimelineMax();
tl_1.to(el, 2, {left:10});
tl_1.to(el, 1, {top:20});
//then you can control that instance:
tl_1.pause();
tl_1.resume();
tl_1.seek(1.5);
...etc...

What may have confused you is that there are some static methods available on TweenMax and TweenLite that make it easier to create tweens without using the "new" constructor and assigning an instance to a variable. In other words:

//instead of this:
var tween = new TweenMax(...);
//you can do this and get the same result:
TweenMax.to(...);

But don't mistake those convenience static methods to mean that you're supposed to control everything through static methods. That actually couldn't work because what if you need to have one set of animations paused while another one plays? Or alter the timeScale of only one set? If all the controls hung off the static TweenMax or TimelineMax class, it'd get super clunky ;)

 

Hang in there through the learning curve - we consistently hear from developers that they absolutely love GSAP and how intuitive (and flexible) the API is. If things seem confusing to you right now, I'm pretty confident that if you play with it a bit longer, the light bulb will go on and you'll see how it all makes sense. 

  • Like 3
Link to comment
Share on other sites

  • 3 years later...

If I create a normal TweenMax, TweenLite can I reverse it?

Or reverse is only reserved for timelines.

 

Update:

I looked through the documentation, it seems that TweenMax allows reverse.

 

It is all working fine until I add my tween into a timeline.

See the Pen xEykQX by vennsoh (@vennsoh) on CodePen

 

How can make store an independent tween while adding it to a timeline.

 

Later on I would like to tween.reverse() it by triggering some events.

Link to comment
Share on other sites

Sure, all animation classes share a common reverse() method (as well as most other basic methods for control, like pause(), resume(), timeScale(), seek(), etc.).

var tween = TweenMax.to(...);
//then later...
tween.reverse();

Note that when you reverse(), it just makes the playhead go backward toward the start from wherever it is currently. So if you call reverse() when the tween has already played for 1.25 seconds, it will then take 1.25 seconds to reach the beginning again. If you want it to jump to the end and play backward, you can call tween.progress(1).reverse(). 

 

Does that help?

  • Like 1
Link to comment
Share on other sites

Sure, all animation classes share a common reverse() method (as well as most other basic methods for control, like pause(), resume(), timeScale(), seek(), etc.).

var tween = TweenMax.to(...);
//then later...
tween.reverse();

Note that when you reverse(), it just makes the playhead go backward toward the start from wherever it is currently. So if you call reverse() when the tween has already played for 1.25 seconds, it will then take 1.25 seconds to reach the beginning again. If you want it to jump to the end and play backward, you can call tween.progress(1).reverse(). 

 

Does that help?

 

Thanks Jack, I got that part. I further elaborate my problem.

 

See the Pen xEykQX by vennsoh (@vennsoh) on CodePen

 

 

How can make store an independent tween while adding it to a timeline.

 

Later on I would like to tween.reverse() it by triggering some events.

 

It seems to just jump to the end of the timeline or start of it. It doesn't tween?

Link to comment
Share on other sites

A tween's playhead is always determined by its parent timeline's. In your codepen, you're reversing the tween while it's inside a timeline whose playhead is already at its end, thus when you reverse direction of the tween, it will immediately render at its starting state. That's exactly how it's supposed to work. Otherwise, the state of the timeline wouldn't be correct.

 

I'm curious - why are you using a timeline at all? And why are you trying to reverse only 1 tween inside of a timeline instead of reversing the whole timeline? Perhaps if you help us understand your goal, we can offer some solutions. 

  • Like 1
Link to comment
Share on other sites

Thanks Jack.

 

I see.

 

What I am trying to achieve is that I have a timeline like.

homepageTL
.add(playSplit, "start")
.add(tweenCTA, "start+=1.125")
.add(tweenIconAll, "start+=2.25")
.add(tweenSelector, "start+=2.25")
.add(tweenLogo, "start+=2.25")

playSplit is a function, the rest are tweens.

 

I intentionally split the tweens out as I want to reuse them separately.

And in cases, I would like to play this set of tweens in sequential order.

 

Sometimes I would like to reverse the tween individually depending on scenario.

Eg: click on this button, revese tweenCTA and tweenSelector concurrently.

 

I hope that makes sense.

Link to comment
Share on other sites

I tried doing something like this.

 

I have 4 tweens, 1 timelineA that I want to animate.

 

My main timeline will house all 4 tweens and 1 timelineA.

 

I create a separate timeline for the reverse that will house timelineA.reverse, tweenA.reverse() and tweenB.reverse().

tweenA, tweenB, tweenC, tweenD

tlA, tlMain, tlReverse

tlMain = new TimelineMax();
tlReverse = new TimelineMax({paused: true});

tlMain
.add(tlA)
.add(tweenA)
.add(tweenB)
.add(tweenC)
.add(tweenD)

tlReverse
.add(tlA.reverse())
.add(tweenA.reverse())
.add(tweenB.reverse())
 

When the user visits the page,

It will play tlMain.

 

When the user clicks on a button, it will play tlReverse.

 

It looks like a sound solution?

 

However it is not behaving as expected. It is like tlReverse is played even before I click on the button.

Link to comment
Share on other sites

I don't think it's wise to reuse a single instance in all those cases because it sounds like you'll have too many different pieces all trying to control the same playhead (and potentially conflicting). Well, you could do it by pressing other tweens into service for controlling the playheads, but I'm not sure you'd find it as intuitive. Example:

homepageTL.to(tweenCTA, tweenCTA.duration(), {time:tweenCTA.duration(), ease:Linear.easeNone}, "start+=1.125")
  .to(tweenIconAll, tweenIconAll.duration(), {time:tweenIconAll.duration(), ease:Linear.easeNone}, "start+=2.25")
  ...

Notice I'm literally using other tweens to animate the playhead of your "real" tweens. 

 

But if I were you, I'd probably take a more straightforward approach instead, and just tween to the values you need when you need them. Create new tweens - we've made the system extremely efficient, so you don't need to feel like you've gotta reuse instances to be efficient. 

 

So, for example, if you've got a button rollover that plays/reverses a tween, that's fine, but then for your timeline animation just create a new tween for that.

 

Make sense? 

 

Also, whenever I see somebody adding a bunch of tweens using labels with relative times like "start+=1.125", "start+=2.25", "start+=2.25", etc., I want to make sure they know about the power of nested timelines because those could really help make your code more modular and easier to edit. For example:

function buildStart() {
    var tl = new TimelineLite();
    tl.add(playSplit)
      .add(tweenCTA, 1.125)
      .add(tweenIconAll, 2.25)
      .add(tweenSelector, 2.25)
      .add(tweenLogo, 2.25);
    return tl;
}

var master = new TimelineLite();
master.add(buildStart(), "start");

Then, you can create a function for each section of your animation, and just have that function spit back a timeline that you nest wherever you want into a master timeline. Once you do that a few times, it's a game-changer for your workflow. You can then take entire chunks and move them around, and isolate individual chunks in their own intuitively-named functions, etc.   

  • Like 2
Link to comment
Share on other sites

(I was typing my post when you were adding your other one...)

 

The reason your code didn't work was that you were adding a bunch of tweens to one timeline, then (before anything played), you were reversing the SAME tweens and adding them to a different timeline (which removes them from the previous parent). Think of tweens like DOM nodes - they cannot have multiple parents. They must live somewhere (can't be two places at one time). Otherwise, imagine what would happen to their playhead if two different timelines were both fighting for control, one going forward, the other backward. 

  • Like 2
Link to comment
Share on other sites

Thanks Jack!

 

GSAP skill +1 again.

 

Sorry for the constant reply as I have spent my whole afternoon - evening trying to figure this out.

Trying different ways.

 

-

 

So can I say, 

  • In a timeline, it is always "SAFER", in fact "BEST" to add "functions". The functions will be reusable.

  • Adding tweens or timelines within another timeline can cause conflicts if not careful.

  • Add a tween variable within a timeline if you want to remove it from the timeline later? <-- This is a trick I read from the forum. Eg: performing .reverse() without just that tween.

Link to comment
Share on other sites

Well, I'd say a qualified "not really" to all of those points actually :)

 

  • The example wasn't about adding functions to a timeline at all. Notice I'm calling the function at the point of insertion, thus it's adding the RESULT (returned value) of the function. In this case, a TimelineLite instance. A longer-hand version would look like:
    var child = buildStart(); //<-- returns a TimelineLite
    master.add(child, "start"); //<-- put it into the master timeline at a label "start"
  • No, adding tweens or timelines within another timeline is not dangerous at all. In fact, the whole GSAP system was specifically engineered to make this super easy and extremely powerful. The problematic thing you were doing was trying to add the SAME tween to MULTIPLE timelines (and also controlling it individually outside the timeline). 
  • Yes, you can assign a tween to a variable if you need to remove it later, like tween.kill() or timeline.remove(tween) but you could also use timeline.kill(null, yourTarget) or TweenLite.killTweensOf(yourTarget) if you want to kill the tweens of a particular target. Lots of options actually (I could list others, but I don't want to make this response too long)

Keep playing with it and I'm confident the light bulb will go on and you'll feel empowered. 

 

Happy tweening!

  • Like 1
Link to comment
Share on other sites

I'm not sure I understand the difference. Adding a function to a timeline and calling a function within a timeline sound like the same thing to me.

 

Perhaps you mean this:

//option 1:
var tl = new TimelineLite();
tl.add(callMyFunction, "start");
function callMyFunction() {
    //a bunch of tweens or timeline that get fired independently, not inserted into tl
}

//option 2:
var tl = new TimelineLite();
tl.add( section1(), "start");
function section1() {
    var tl = new TimelineLite();
    //add a bunch of animations...
    return tl;
}

If that's what you're asking, I would DEFINITELY say option 2 is almost always best because you're putting it into a master timeline that you can control. Moving the playhead of that master (like with seek() or reverse() or whatever) affects all of its nested animations. If you just fire off things in random functions that get called from timelines, it's fine in some cases, but you get limited control. For example, if you fire those off when the timeline is going forward, and then you reverse that master timeline, it won't make any of those animations go backward because they're not embedded in that master timeline at all. They just fire off, finish, and get garbage collected. Done. 

 

Make more sense now? 

  • Like 3
Link to comment
Share on other sites

  • 5 years later...

here's a way to simulate reverse with yoyo() in combination with negative "delay".
(delay has to be negative to duration)
Works for one tween. If you use many other, you have to reOrder the tweens also

tl.fromTo('.reverseSim', {opacity:1,scale:2},{
  duration: 4,
  opacity: 1,
delay:-4,
  yoyo:true,
  repeat:1,
  scale:1
},'0')

 

  • Like 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.
×
×
  • Create New...