Jump to content


Objects' tweens moving inconsistently after replay in Timeline

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'm almost finished with my first greensock-driven HTML animation and I am running into a problem with how I created some randomly positioned elements that also tween to random positions in a specified x/y range.


The situation is that I needed to place about 20 or so little dudes on the stage and have them appear to float around organically. Then a subset of them needed to be tweened separately than the rest, so they could get circled and get pulled into a funnel. The first time the animation plays the tween works fine, but after a replay instance, or if scrubbing back and forth, the elements pause in place for a few seconds and then the tween hops around disrupting the smooth organic feeling of the floating dudes. I've posted a codepen and a also a demo file for viewing here, respectively:

See the Pen lsDvk by jsring (@jsring) on CodePen

| demo


Perhaps what could have solved the problem would have been to create each instance of the little dudes in a more programatic way and have them each tween around the stage more randomly rather than coding them the way I did with specific times. I tried that at first, but even with their positions placed using Math.Random they all followed the same exact random path. I would love to get some insight on how I could have done this more smarter. I appreciate any help. Also, I am relatively new to Javascript. Thanks!

Link to comment
Share on other sites

Hi and welcome to the GreenSock forums.


Glad to hear you have had such success with GSAP. Your animation is really nice.


Also, its great that your created the CodePen version... that is very helpful...  but we really need a reduced test case.


The animation is 30 seconds long. There are 200 lines of code (much more considering chaining) and tons on objects animating.


Usually when a timeline plays fine once, but different on repeat or reverse its because you have conflicting tweens meaning that multiple tweens at the same time are trying to animate the same properties of the same object. When this conflict occurs the newer tweens will kill the older ones. So basically when you try to play those tweens again... nothing happens.


I tried to assess where this might be happening, but simply got overwhelmed by the amount of code. And quite frankly even after watching the animation a few times... it wasn't clear where it was happening or what was wrong.


Please reduce that example as much as possible. If the problem only happens with the dudes, remove everything that isn't a dude. 


I'm sure if you can boil this down to a simple illustration of the issue, I or someone else will be very well suited to help you figure it out.



  • Like 3
Link to comment
Share on other sites

yes i had a hard time trying to determine was what causing it to, due to the large amount of code.. very interesting animation though :)

Link to comment
Share on other sites



Usually when a timeline plays fine once, but different on repeat or reverse its because you have conflicting tweens meaning that multiple tweens at the same time are trying to animate the same properties of the same object. 


Thanks for the comments thus far. Here is a culled-down codepen with just the dudes and the play controls:

See the Pen JdazF by jsring (@jsring) on CodePen


Carl, The quote above from your post is exactly what I believe is causing the problem. I am certain that I am tweening conflicting properties with the dudes, and I even know why. The problem is that I don't know how not to. I have a bunch of guys floating around for fifteen seconds or so, but 80% of the way through, some of the dudes need to change their course dramatically and organically. I am not sure if I should have tried tweening this with bezier curves or something, but with the randomness of direction it seems math could do this for me, instead trying to plot a hundred bezier coordinates. I believe there must be a way to solve this problem of moving the dudes and then course correcting for the subset of dudes using a lot less code. I really appreciate the effort you made thus far in helping me out.


Note: the problem is especially clear when the dudes get circled after being scrubbed or repeated. You'll notice they just stop and then jump to a random location.

Link to comment
Share on other sites

There's still a lot code and I have quite some trouble following it (specially without any comments).

While writing a longer reply I realized that this is an overwrite conflict. Turns out that the staggerTo instance at the end of the timeline tweens the values of bottom and left. At the same time the humongous amount of instances before that are tweening top and left, thus creating the conflict. If you change the staggerTo to this:

.staggerTo(["#dudeP","#dudeQ","#dudeR","#dudeS","#dudeT","#dudeU"], 0.9, { y:600, x:5, ease:Back.easeIn.config(3)}, 0.2, "dudesMove+=13.5")

It works, because you're tweening x and y, therefore there's no conflict between this instance and any other in the timeline.



  • Like 1
Link to comment
Share on other sites

Rodrigo, You're the man, thank you, that worked for now. In the future I'd love to figure out how to recreate what I did with only a few lines of code, converting all of those tweens into some kind of function, or finding some other method to create the randomness that I need to happen.


Thanks again!

Link to comment
Share on other sites

You're welcome.


Well all the dudes follow the same pattern:

.set("#dudeU", { bottom:getRandomY(), left:getRandomX(), rotation:getRandomRotation() },"dudesMove")

.to("#dudeU", 7, { bottom:getRandomY(), left:getRandomX(), rotation:getRandomRotation(), ease:Linear.easeNone}, "dudesMove+=1.95")

.from("#dudeU", 1.5, { autoAlpha:0 }, "dudesMove+=2.15") .to("#dudeU", 7.5, { bottom:getRandomY(), left:getRDripX(),  rotation:getRandomRotation(), ease:Linear.easeNone}, "dudesMove+=8.95")

.to("#dudeU", 0.25, {scale:0.7, ease:Back.easeIn}, "dudesMove+=10.61")

.to("#dudeU", 0.25, {scale:1, ease:Back.easeOut}, "dudesMove+=10.81")

What changes are instance's durations and the relative position. What you could do is create a function that takes the specific durations and dude ID and return a timeline with those parameters.


Also my advice is that for this cases is better to create a single timeline for each element and then add the timeline to a master one and not create a huge timeline. This makes changing times, parameters, etc, quite faster and simplifies code reading/debugging.


Take a look at this video Carl made, is a great learning resource:




Happy tweening!!

  • Like 3
Link to comment
Share on other sites



Thanks a ton for the reduced sample. So much nicer. Sorry, I didn't have time to dig in until now, but as you see it really helped Rodrigo come up with a quick and quite clever solution. Not so sure I would have thought of that.


I do want to add just a touch more about how the conflicts were causing overwrites/kills to happen. In most cases this actually a very good thing. I forked your example just to illustrate what would happen if new tweens didn't kill conflicting tweens.




Note the overwrite:none on the staggerTo at the end.

Since I'm telling the engine to ignore the default overwriting, now multiple tweens are concurrently running on the same properties of the same objects. You'll notice that your guys wander and then jump up and out of the funnel... but when the jump action ends notice the wander continues.


Technically speaking the lateral wander and the vertical jumping were happening at the same time, but the jump tweens were the ones that got to modify the bottom / left values right before the render... but when the jump tweens ended that's when the wander tweens resumed from where they would have been had the jumps never happened. 


I think Rodrigo's solution is perfect for this situation, but I also think you could build timelines for each dude that accounted for the fact that they need to wander for x amount of seconds and then transition them into the jump. And yeah a function or loop could probably cut that code down to about 15% of its current size.


All in due time. Its great that you got this far. Its all part of the learning process.


Although this example: http://codepen.io/GreenSock/pen/Kajpu Uses canvas instead of DOM elements, it shows how you can basically make a whole bunch of objects animate in similar yet random ways by creating a loop that creates custom animations (timelines) for each one and you add() those timelines to a main timeline. Very powerful.

  • Like 1
Link to comment
Share on other sites

Thanks, Carl!


I really dig the amount of help and great info you guys give. When I started this little project, I was asked to use Adobe Edge but I insisted on using gsap alone for performance reasons. I have not been disappointed. One of the original scenes that I created for this project, which unfortunately ended up getting cut out, was

See the Pen EiDpt by jsring (@jsring) on CodePen

entering the stage as a series of rings which I created with only a precious few lines of code. It worked out so well it cemented my belief that I had made the right choice about using and gsap. That part of the project was also my first ever code pen. I hope to be able to duplicate this kind of efficiency for every future tween.


You guys are the best, thanks again!

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