Jump to content


Sequencing animations along beziers

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 guys, thanks for making a great product.

I'm still trying to wrap my head around the logic of sequencing with GSAP. I've defined a whole stage show worth of animations. To make my little characters act I've used GSAP to animate sprite sheets using these techniques (link:

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

) and to make them move around I've defined a whole bunch of tweens along complex twining bezier curves using the GSAP bezier plugin.

I've set up all these animations individually, set them to {paused: true} and saved them as javascript variables. Now I just need to figure out how to sequence them nicely on a timeline. My current challenge is how to tell an animation along a bezier curve to stop (reverse, resume, etc) at a particular point in the timeline.

This code pen (

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

) has a minimal working example. I'd like the blue square to start follow its bez at 0 seconds, to pause at 5 seconds and resume at 8 seconds. Meanwhile, the squeare should continue to be animated exactly as it is now (i.e., I don't want to pause the entire timeline, just one element).

My basic intuition is to do something like this:

tl.add(blue_path.play(), 0);
tl.add(blue_path.pause(), 5);
tl.add(blue_path.play(), 8);

but this simply causes the blue_path animation to pause until the 8-second mark.

A working alternative I've found is to do this:

tl.add(blue_path.play(), 0);
tl.add(function(){blue_path.pause();}, 5);
tl.add(function(){blue_path.play();}, 8);

The trouble is, using this method I can no longer use the seek methods of the timeline itself. For example: tl.seek(6) would jump over the "pause" instruction above...

Thanks for any help you can offer. I'm probably overlooking something simple or misunderstanding the logic of this system, but I've been struggling with this for days and could really use some guidance.


Link to comment
Share on other sites

Sure, it can be a little bit of a logic puzzle to get your head around how this works, but instead of adding your tween and calling pause/play at various times, you can just tween the progress of your tween (fancy!) and introduce pauses where ever you need, while still maintaining complete ability to seek accurately:


var tween = TweenMax.to(target, 8, { foo: bar, paused: true });
// keep it paused - tween doesn't need to compete with its progress being updated

// tween until 5 seconds, then stop, then resume from 8 seconds
tl.to(tween, 5, { progress: 5/8, ease: Power0.easeNone }, 0);
tl.to(tween, 3, { progress: 1, ease: Power0.easeNone }, 8);

// or using time:
tl.to(tween, 5, { time: 5, ease: Power0.easeNone }, 0);
tl.to(tween, 3, { time: 8, ease: Power0.easeNone }, 8);
Super minimal example:

See the Pen IxjBq by jamiejefferson (@jamiejefferson) on CodePen



P.S. if you include parentheses () after a function name, it's called immediately. The syntax for your first intuition would have been something like this (but still not quite what you're after):

tl.add(blue_path.pause, null, blue_path, 5);
tl.add(blue_path.resume, null, blue_path, 8);
// pausing only prevents render updates to a child of a timeline, it 
// doesn't adjust the position of the tween. since blue_path has a
// start time of 0 it will always finish at 8 seconds, whether you
// pause or not
  • Like 4
Link to comment
Share on other sites

Hi and welcome to the GreenSock forums.


Glad to hear you are having such success with the platform.

Your question actually reveals one of the more powerful features of the platform that users don't usually appreciate until further down their path.


-- and it seems Jamie has revealed this to you just now;)


But yes, you can tween the time(), progress() and timeScale() of any animation.


In simple terms you can tween the time() of a tween like so:

var blue_path = TweenMax.to("#blueBox", 8, {bezier:{type: 'quadratic', values: walk_path_bez}, paused: true});

//take 2 seconds to advance the time() of blue_path to 4 seconds and use a Bounce easse  
TweenLite.to(blue_path, 2, {time:4, ease:Bounce.easeOut}, 0)

demo: http://codepen.io/GreenSock/pen/CvgxK?editors=001


Now that we can tween the time() of a tween, like Jamie said, we don't need to add the tween itself to your timeline, we can just add tweens that tween the time of blue_path like so


var tl = new TimelineLite();

tl.add(red_path.play(), 1)
  .to(blue_path, 5, {time:5, ease:Linear.easeNone}, 0)
  .to(blue_path, 3, {time:8, ease:Linear.easeNone}, 8)

demo: http://codepen.io/GreenSock/pen/BrHmv?editors=001


This exact same technique was used in our fancy homepage animation where all the green dots are flying around and we illustrate that you can pause, play, reverse and change timeScale of an animation




This is the relevant code for that tweens the time of the dots timeline


tl.to(dots, 2.2, {time:2.2, ease:Linear.easeNone}, 0);
  tl.from("#control", 0.5, {left:"+=100", autoAlpha:0}, 0);
  tl.from(pause, 0.4, {autoAlpha:0, scale:2}, 2);
  tl.from(play, 0.4, {autoAlpha:0, scale:2}, 4);
  tl.to(dots, 2, {time:4.2, ease:Linear.easeNone}, 4.2);
  tl.from(reverse, 0.4, {autoAlpha:0, scale:2}, 6);
  tl.to(dots, 2, {time:2.2, ease:Linear.easeNone}, 6.2);
  tl.from(timeScale, 0.4, {autoAlpha:0, scale:2}, 8);
  tl.to(dots, 2, {time:3.2, ease:Linear.easeNone}, 8.2);
  tl.from(subEnd, 0.4, {autoAlpha:0}, 10);
  tl.to(dots, 3, {time:dots.duration(), ease:Linear.easeNone}, 10.2);

And lastly to see how tweening the timeScale() of a tween works:


  • Like 4
Link to comment
Share on other sites

Brilliant .. I learned alot about using time() Carl and Jamie.. thanks for your examples and explanation! :)

  • Like 1
Link to comment
Share on other sites

Awesome! It all makes sense now. The tween objects themselves have properties (time, progress, timeScale) which can themselves be tweened. Very nice.


Thank you kindly for your prompt and helpful replies. This framework and community are a pleasure to work with.

  • Like 2
Link to comment
Share on other sites

I was writing out a follow-up question, but solved it myself. I thought I'd post the answer anyway, since I've already written it out and it might help someone else one day.


How do I simultaneously pause and unpause a SteppedEase infinitely repeating animation?


Using your answers I'm now able to have my little guys wander around their bezier paths. However I'm also animating their wanderings using a spritesheet and a looping SteppedEase easing. I've demonstrated a minimal example here:


See the Pen hylHC?editors=001 by anon (@anon) on CodePen


, where instead of animating a sprite sheet, I'm just counting the frames from 0 to 3. That count should stop wherever it's up to when the blue box pauses, and resume when the blue box starts moving again.


I eventually achieve this by tweening the timescale property to zero (as demonstrated in the codepen carl schooff linked to), with an animation time of zero:


tl.to(repeating_animation, 0, {timeScale:0}, 2)
tl.to(repeating_animation 0, {timeScale:1}, 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.