Jump to content
Search Community

Seek causes timeline to jump on transition when two similar tweens are found

annam 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

I am using seek() to make sure that all tweens in the timeline are initialized, in case I need to reverse it later (as per this conversation: http://greensock.com/forums/topic/8161-tweenfromto-doesnt-trigger-tweens-that-have-not-yet-been-reached-by-normal-play/)

tl.seek(tl.totalDuration()).play(0)

I've come across an issue where if you try to tween the same property in the same timeline more than once, seek causes that specific property to jump to a previous tweens' value on play(0), instead of its initial value. All other properties continue to tween:

 

https://jsfiddle.net/annam/qoe6zwob/4/

 

(try switching the simple play() to see how it should behave)

 

I'm sure it's not best practise to overwrite tweens, but the nature of the project is such that the tweens are generated dynamically and this could happen. Is this a bug in calculating the original position of the tween? Is there any way to work around this issue?

 

Thanks so much!

Anna

 

 

 

 

See the Pen 4 by annam (@annam) on CodePen

Link to comment
Share on other sites

Thanks for the demo.

 

Yes, an overwrite is happening and there are no bugs. Although its simple enough to see that your second tween is the culprit, here is a handy way of debugging overwrites:

TweenLite.onOverwrite = function(overwritten, overwriting){
   console.log("overwritten tween");
   console.log(overwritten)
   console.log("startTime of overwriting tween " + overwriting.startTime())
}

https://jsfiddle.net/26n7aznj/3/

 

I've come across an issue where if you try to tween the same property in the same timeline more than once, seek causes that specific property to jump to a previous tweens' value on play(0)

 

 

This is mostly true but its critical to note that an overwrite only happens if 2 tweens fight for control over the same properties of the same object at the same time. You can have many tweens controlling the same properties of the same objects in a timeline as long as they don't overlap.

 

When 2 tweens are fighting for control over the same property there are 2 potential outcomes:

 

  1. The most recently created tween kills the previous tween and gains control of setting the values of those properties (default behavior). In your current example the first tween gets killed which means that on subsequent plays of the timeline it is as if that tween no longer exists.
  2. Both tweens fight to change those properties on every tick of the engine (no overwriting) and the tween with the longer duration will continue playing after the other tween is done. This can often result in unsightly results. Notice how the first tween resumes after the second tween ends: http://codepen.io/GreenSock/pen/bEBRrG?editors=001

In order for your example to work as you intend, set overwrite:"none" on your second tween.

 

tl.to('#box', 1, { x: 100 }, 0)
  .to('#box', 1, { x: 200, overwrite:"none" }, 0.1)
  .to('#box', 1, { backgroundColor: 'red'}, 0);

This should work fine as long as the second tween doesn't end before the first tween.

 

 

 

  • Like 1
Link to comment
Share on other sites

ok, after further review it appears things are working as designed, but this would be a tricky edge case to accommodate and it would inflict a performance penalty on everyone.

 

var tl = new TimelineMax({ paused: true });
tl.add(TweenLite.to('#box', 1, { x: 500 }), 0);
tl.add(TweenLite.to('#box', 1, { x: 600, overwrite: 'none' }), 0.001);

 

The main issue is that when you seek to the end of the timeline instantly the engine needs to calculate how each tween is going to render in its "end" state.

The timeline must loop through its child tweens (in order) and make them render at that appropriate time. So you've got x going to 500 on the first tween. Done. It makes x 500. Now it moves to the next tween and instantiates that and renders it at its end. Here’s the key problem: what is that tween's STARTING value? Well, the tween right before that rendered x at 500. Now this 2nd tween says “okay, I’m a to() tween, so record the starting value as whatever it is currently…oh, it’s 500…so I’m tweening from 500 to 600”. Boom. There’s the problem.

 

In order to account for the overlapping tweens we would have to add logic that tries to analyze every situation and say “oh, wait, I found an overlap…let’s rewind that other tween to the exact moment of the overlap, make it render there, and then instantiate the other tween”? This could become very costly from a performance standpoint and add a considerable amount of code (bloat).

 

In general we suggest avoiding creating overlapping tweens in a timeline, but if you want to get around this what you can do is force the timeline to render at the time of the overlap which will give you the proper starting values for the second tween like:

tl.seek(0.001).seek(tl.totalDuration()).play(0);

Check it out here: https://jsfiddle.net/hoLuae34/

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