Jump to content
Search Community

Bezier and Nested Timelines

celli 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

Hi, I was going to start experimenting with the bezier curves in greensock, and I like the example of the bug moving along the curve and then dispersing at random points along the bezier, as noted in the codePen URL from GreenSock.


My Question is ,if I wanted to replace the 'bug' in this example with something animating, like a butterfly flapping her wings, and then animate that flapping butterfly along the bezier. What would be the best way be, to go about this with GSAP ?


Similar to if I started out with a looping movieclip in Flash that had flapping wings -- and then I placed that into another timeline and moved the flapping winged timeline along a bezier (a second timeline) ? This will help me in general with nesting timelines properly with GSAP.


Maybe I can create a timeline that doesn't play, but attach a variable to it -- and then insert that into another timeline that moves along a bezier ? What's the best way to build something like that with GSAP ?

See the Pen Kajpu?editors=001 by GreenSock (@GreenSock) on CodePen

Link to comment
Share on other sites

Hi :)


your greensock codepen's using KineticJS framework ( Kinetic plugin ) and html5 canvas , for DOM obj use this method :

See the Pen LuIJj by GreenSock (@GreenSock) on CodePen


and yes , i think it's the best way that you animate flapping wings at first and then create a bezierTween for the container of wings (butterfly) like flash workflow .

  • Like 1
Link to comment
Share on other sites

There are definitely a variety of ways to handle this, and GSAP can support nesting as many timelines as you like.

In the next demo each creature has a timeline that


- moves the creature along a bezier path

- scales the creature in a pulsing fashion as it moves

- rotates a number above the creatures head




Notice that as you scrub the timeline slowly with the slider, all animations are being controlled.


I provide this just to show that it isn't always necessary to create a lot of individual timelines.


Oh and here is the CSS version of the Kinetic one you posted before I messed it up with those additional animations:) 


  • Like 2
Link to comment
Share on other sites



This is a very rough sample of creating the wing flap using a sprite sheet and animating the element though a bezier curve. Basically change the background position using a timeline and then use the bezier plugin in a different timeline. Also if you want total control and you could nest both timelines in a parent one.


Finally if you're working with a lot of elements I'd recommend you to take a look at Pixi (if is just one butterfly, it should be ok with DOM elements), for two reasons, first it renders using WebGL when the browser supports (canvas rendering when there's no WebGL) it giving you a great performance and second it has a very solid way to handle spritesheets. It's very easy to access the elements created by it and more important you can control everything in the wing flap animation through GSAP (which ultimately is very convenient).


Here's the link:


See the Pen dxmie by rhernando (@rhernando) on CodePen



  • Like 2
Link to comment
Share on other sites

These examples really expanded my understanding of how GSAP works, thanks! I really like the slow pause and slow-start buttons done very simply like this:

pause.onclick = function(){
  TweenLite.to(bezierTween, 1, {timeScale:0});

But I am still a little lost on exactly how to nest a timeline into another timeline. For instance Ancient Warrior's example use the the element #creature placed into a timeline and animated, which I understand... But can I replace #creature with another timeline that I create ? Something like this:

bezierTween = new TweenMax("ANOTHER TIMELINE HERE", 6, {
      values:[{x:150, y:300}, {x:300, y:30}, {x:500 + Math.random() *100, y:320*Math.random() + 50}, {x:650, y:320*Math.random() + 50}, {x:900, y:100}, {x:990, y:400}],
  ease:Linear.easeNone, repeat:-1});

So where it says "Another Timeline Here' ...Can I do that ? And what would I do..., just pause the 'other timeline' so it doesn't run alone and set it somehow so it only runs inside of my bezier timeline, (which is my container timeline) ? This is where I am confused...

Link to comment
Share on other sites

Nice job, AW.


Celli, I think the problem is that GSAP timelines are very similar to MovieClips but they are not the same. 


In Flash a MovieClip is a physical container for animated visual elements (other symbols, shapes, bitmaps).

As such you can literally place 2 MovieClips of spinning wheels inside a MovieClip of a car. When the car moves, the wheels spin and everything is great.


In GSAP, a TimelineLite/Max simply holds instructions about animating DOM elements (or properties of any javascript object). Timelines do not contain DOM elements, they simply tell them what to do. A timeline contains instructions for animating multiple DOM elements that can be anywhere in the DOM regardless of parent-children relationships. 


When you nest a timeline inside another timeline, it basically means that the child timeline will advance when the parent timeline advances (which makes building complex animations with tons of items animating super simple to control by just telling the parent timeline what to do). And unlike a MovieClip, a TimelineLite/Max instance can not be duplicated. In other words, you can't say "let's create a wing-flapping timeline and put it in butterfly1 and butterfly2". You will need to create a unique wing flapping animation for each butterfly (which can be simplified by using a loop)


I'm confident that once you detach yourself from the MovieClip metaphor and focus more on some basic timeline examples, it will click, and you will continue to make amazing things.


Here is another very basic example of nesting timelines:



And taken to the extreme, nesting timelines allows you to do:


  • Like 1
Link to comment
Share on other sites

Yes ! This reveals the concept to me very well. I see the pulsing GSAP on-top of the 'creature' and now I get it :) All of the other examples really help, I am going to deconstruct them all, and work this in. Awesome explanations, thanks!


One question:

In this example: 

See the Pen bkLwt by GreenSock (@GreenSock) on CodePen

What pauses the 3 timelines (outside of the master Timeline) ? Is it only because their time is specified in the 'master Timeline' ? If the 'master Timeline' wasn't there, I assume they would all run together, is that right ?

Link to comment
Share on other sites

Yes, once they get added to the master timeline they will not run until the master timeline's playhead gets to their insertion time.


if you remove the code that adds them to the master, you will see that they will all get created and run at once.


Glad these explanations are helping.

Link to comment
Share on other sites

  • 2 weeks later...

I have been working on bezier animating, and nesting timelines and it is working very well.

I have one more question now relating to how you were able to get the 'creatures' to multiply, and create various creatures at random positions.


I am able to animate on the bezier, and randomize the positions with the code below

var bubbleTL1 = new TimelineMax({repeat:-1});
bubbleTL1.to(".blenderCircle", 2, {bezier:{type:"soft", values:[{x:5 + Math.random() *100, y:-20}, {x:-5 - Math.random() *100, y:-40}, {x:5 + Math.random() *100, y:-100, opacity:0}], autoRotate:true}, ease:Power1.easeInOut})
.to(".blenderCircle", 1, {css:{opacity:0}, ease: Sine.easeOut}, "-=1")
.to(".blenderCircle", 2, {scale:".5" }, "-=1");

But when I try and add the function to create a bunch of tweens and add them to a timeline, I can't get it to work properly.


Here's what I did with simplifiedcode, I wrapped the original timeline in a function called 'getAnimation' just like your example here: 

See the Pen kyluC?editors=001 by GreenSock (@GreenSock) on CodePen

And then I am trying to use the function you created to build the timeline and create a bunch of Tweens -- But this is where I can't seem to get it to work.

//wrapped my timeline in a function called getAnimation
function getAnimation() {
 var bubbleTL1 = new TimelineMax({repeat:-1});
bubbleTL1.to(".blenderCircle", 2, {bezier:{type:"soft", values:[{x:5 + Math.random() *100, y:-20}, {x:-5 - Math.random() *100, y:-40}, {x:5 + Math.random() *100, y:-100, opacity:0}], autoRotate:true}, ease:Power1.easeInOut})
.to(".blenderCircle", 1, {css:{opacity:0}, ease: Sine.easeOut}, "-=1")
.to(".blenderCircle", 2, {scale:".5" }, "-=1");
 return bubbleTL1;

//create a bunch of Bezier tweens and add them to a timeline
function buildTimeline() {
tl = new TimelineMax({repeat:-1});
for (i = 0 ; i< 20; i++){
//start creature animation every 0.17 seconds
tl.add(getAnimation(i), i * 0.17); } }


What am I missing ? I must be missing something here...

Link to comment
Share on other sites

Hi celli  :)


yeap, you missed some things , pls compare your code to the codepen and fix these issues :


1 - where you generate the blenderCircles in getAnimation function !!!

2 - in getAnimation function where you append the blenderCircles in container  !!!

3 - most of your points for bezier are out of view !!! atlast in a full size container 

4 - check other things like your tweens delay/gaps , ease and ...

Link to comment
Share on other sites

Yeah it seems like some key things are missing. I can only assume that perhaps elements with class "blenderCircle" already exist in the DOM, but this is why we like seeing CodePen demos, so we can see all the html, css and js.


Assuming those elements do exist, a problem may be that each time you create a new bubbleTL1 timeline you are using ".blenderCircle" as your selector which means all blenderCircles are being animated at the same time in that new timeline. And you may be creating new tweens in the new timeline that conflict (overwrite) tweens in a previous timeline (as the timing does overlap). 

Link to comment
Share on other sites

Thanks! So, I can alter the codePen, and get things to work -- but the problem is having the container and the creature appended and dynamically created. I can't seem to figure out how to control the starting point of the creature(s) this way. I really just want to have the 'creature' be an element in my HTML, and control the animation with the JS.


Here is a codePen, But if I could just make the 'creature' div in the HTML, then I can more easily control it's starting position. You see how all of the creatures are starting up in a column down the container. But if I wanted to start them all from the center of the container, and not use the  "container.append(element);" code 


See the Pen sreCn by celli (@celli) on CodePen


Also, I guess I can do it this way, but I wanted to add the bezier animation to the dots. And create it so that it looks seamless (without the looping look) So it looks like they are seamlessly floating up from a container 

See the Pen zHuIs by celli (@celli) on CodePen

Link to comment
Share on other sites



There is a semicolon missing in the creature class:

.creature{  background:url(http://www.greensock.com/_img/codepen/bezierCreature/creature_red.png);
  top:200px/*MISSING SEMICOLON*/

Also in order to center the element you could add this code after you add the creature to the DOM:

TweenLite.set(element, {xPercent:-50,yPercent:-50}); 

As for not using append, well I don't know how else you could add the element to the DOM otherwise.


Finally this great codepen by Jamie is what you're looking for in terms of a continuous flow of elements from a point, and in this case a Draggable element:


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

Link to comment
Share on other sites

Thanks! All because I left out the semicolon  :-P


See the Pen sreCn by celli (@celli) on CodePen


With regards to the other codepen you showed me, that's great -- But I can't see where the continuous flow code is. I have a feeling I would need to change the way this one works ? Or is there a piece of this continuous flow I can add into my code pen to make it continuous ?

Link to comment
Share on other sites



Jamie's codepen is very straightforward and takes advantage of GSAP's flexibility, one of Jamie's trademarks must I say.


Basically He creates and add the elements to the container:

for (var i = dotQuantity - 1; i >= 0; i--) {
  dot = document.createElement("div");
  dot.className = "dot";
  TweenLite.set(dot, { xPercent:-50, yPercent:-50, force3D:true });
  dotPool[i] = dot;

And finally he creates the timeline with the call() method:

var explosion = new TimelineMax({ repeat: -1 }).call(shootDot, [emitter], null, 1 / dotQuantity);

What happens is that the function in the timeline is being called constantly and animating each element in sequence, that happens in the shootDot function. How often the callback is fired is determinated by the fourth parameter. In order to get a better grasp of the call() method check the API reference:



  • Like 1
Link to comment
Share on other sites

I think I found a solution. I still need to work on grasping the call() method, but this codePen creates two overlapping timelines, and staggers them a bit with different amounts of particles that gives the effect I'm looking for. It seems continuous, and random, like bubbles from a beaker in a lab: 

See the Pen sreCn by celli (@celli) on CodePen


Do you think this Is this not the best way to do things ? overlapping with a delay to give the illusion of continuous flow...

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