Jump to content
GreenSock

beamish

tweens oddly removed after being dragged and then played

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

Hi All,

 

A rather strange situation:

 

several tweens of the same object are added to a timeline to be played in a cubic bezier format.  This objects is then dragged via Draggable. Then, in the 'onDragEnd' event the timeline to which the object had been added to is played starting from 0.  I set a breakpoint after calling the play() function, and then make a call to TweenMax.getAllTweens().  The first time the object is dragged I see all the tweens that should have been on the timeline.  However, after the 'onDragEnd' function ends, the browser steps into the code inside Draggable.min.js which continues on, and then if I make another call to TweenMax.getAllTweens() (while still in Draggable.min.js) then the tweens that were dragged no longer exist.  What is no less odd is that if I drag the object again, play() is called again and works as if the tweens had not been removed, yet still TweenMax.getAllTweens() returns a list without the instances that had been dragged...  Despite the fact that the removal of the tween happend inside Draggable.min.js, if I remove the call to the play() function from the 'onDragEnd' event handler, no tweens are removed...

 

any clues?...

 

Thanks !

 

Elior

Link to comment
Share on other sites

Hello beamish, and Welcome tho the GreenSock Forum!

 

I'm a little confused on the behavior you are seeing. Could you please set up a limited codepen example so we can see your code in action? Everyone here is eager to help but this way we see what your describing in context.

 

Here is a video tut by GreenSock on How to create a codepen demo example.

 

Thanks! :)

Link to comment
Share on other sites

Hi,

 

I ditto Jonathan's suggestion of a codepen that can show us what could be the problem in your app.

 

However just guessing, I assume that your issue has to do with overwriting, perhaps the Draggable instance is overlapping a target element and property, thus killing the timeline's instances. But as Jonathan pointed is better to see a live reduced sample, so please take a look at the link He provided in His reply.

 

Rodrigo.

Link to comment
Share on other sites

Hi guys !

 

Thanks for the warm welcome!  and GSAP looks amazing!

 

I've created the following

See the Pen emdrk by anon (@anon) on CodePen

 , and managed to recreate the problem without using Draggable so it's simpler now.   if you click on the 'number of tweens' button you get '8'; now if you click on 'play', wait till the animation ends, and then click on the 'number of tweens' button again you get 0 (despite the fact the 'overwrite' is set to 'none').

 

Thanks !

 

Elior (beamish is my nick)

Link to comment
Share on other sites

That looks like expected behavior - Since the method only finds tweens that haven't been released for garbage collection, if you create a tween and then let it finish and then a while later try to find it with getTweensOf() or getAllTweens(), it may not be found because it was released by the engine for garbage collection. Remember, one of the best parts of GSAP is that it saves you from the headache of managing gc. Otherwise, you'd need to manually dispose each tween you create, making things much more cumbersome.

 

If you need to keep track of those particular tweens, I'd encourage you to store them in an array yourself (or something like that). 

 

Does that clear things up?

  • Like 2
Link to comment
Share on other sites

Yes, it does clear things, thanks, except for one thing which I probably don't understand right: if I create a tween not on a timeline, as a one-time-play situation, then having it deleted for gc sounds good; however, if the tween is placed on a timeline, and I want to run this timeline several times, and but change the properties of the tweens from one run to another - then I don't see why it is necessary to delete the tweens. For such a situation if I understand correctly, then I have to recreate the entire timeline (i.e. remove all the tweens in it and add them again) if I want to play the timeline again but change a property of one of the tweens.  Wouldn't it be easier if the tweens had not been removed and I could simple access the one I need to change and change it?.. or perhaps, as you suggested, store the tweens in a separate array so they can be accessed via this array to change their properties and then replay the timeline?...

 

Thanks!

Link to comment
Share on other sites

Hi Elior,

 

In order to update the values of a specific instance there are some approaches.

 

You can create a TweenMax instance and use the updateTo() method to change that instance's values. This instance can be stored in a variable so you can access it with ease.

 

If you know which specific timeline children is the one you want to change (the instance's index position that is) you can remove that specific tween, create it again and add it to the timeline with the new values at a specific label (here's when labels become your best friend;)).

 

Finally a live reduced sample would be of great help.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

Thank Rodrigo, I think your help and discussing this issue made it clearer for me now, I think I can now try to implement what I originally tried to do (which is to change properties of tweens dynamically after they have been played and then have them played again).

 

:-)

Link to comment
Share on other sites

Yes, it does clear things, thanks, except for one thing which I probably don't understand right: if I create a tween not on a timeline, as a one-time-play situation, then having it deleted for gc sounds good; however, if the tween is placed on a timeline, and I want to run this timeline several times, and but change the properties of the tweens from one run to another - then I don't see why it is necessary to delete the tweens. For such a situation if I understand correctly, then I have to recreate the entire timeline (i.e. remove all the tweens in it and add them again) if I want to play the timeline again but change a property of one of the tweens.  Wouldn't it be easier if the tweens had not been removed and I could simple access the one I need to change and change it?.. or perhaps, as you suggested, store the tweens in a separate array so they can be accessed via this array to change their properties and then replay the timeline?...

 

Thanks!

 

Just to follow up and clarify why things work this way, here's what happens internally: we keep a lookup table of tweens, organized by target so that we can do super-fast lookups for overwriting behavior. However, as long as the tweens are stored in that lookup table, they cannot be garbage-collected. So we need a way to know when to remove them from the lookup table. Every 120 ticks of the engine, we do a sweep and clean out that lookup table (another performance optimization). Two things make a tween eligible for that sweep: either the tween completed and is on the root timeline, OR it's in a timeline that completed (or that has autoRemoveChildren set to true). 

 

We don't actually do anything to the tweens themselves. You can restart() them, seek(), or whatever, in which case they'll get put right back into that lookup table.  And in fact, if you restart a timeline after it completed, its tweens will get added back too. All of this is automatic. 

 

It isn't safe for us to assume that just because a tween is in a timeline, that it should persist in the lookup table forever (even after that timeline completes). That could cause a memory leak of sorts, or it would require that you manually kill() every timeline you create (most people probably wouldn't remember to do that). 

 

So our system is an attempt to deliver the best of both worlds: super fast performance with lookup tables that automatically clean themselves every 120 ticks to eliminate buildup. 

 

And you do NOT need to re-create all your tweens in order to re-run a timeline. Perhaps you got that impression because I said tweens got eliminated from the lookup table and that sounded to you like I meant it killed/deleted the tweens themselves so that they no longer existed. No, not at all - the tweens remain perfectly intact; they just aren't stored in the lookup table anymore so that they're eligible for garbage collection. If you have a reference to one (or a timeline which has a reference to one), it won't be garbage collected. 

 

Make more sense now? 

  • Like 1
Link to comment
Share on other sites

Hi,

Yes, it makes sense.  I understand the need to remove the tweens from the lookup table so they can be gc after the timeline has completed even if the timeline still exists, and your mechanism sounds right.  I understand the tweens themselves are not deleted as long as they are part of an existing timeline even if it had already completed.  and if I understand correctly, then if I seek() to some point in this timeline then all it's tweens are put back in the lookup table and from there their properties can be changed for the next play(). 

Thank you very much for taking the time to explain all this!

Cheers,

Elior

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