Jump to content


First animation: rotating buttons on a circle.

Moderator Tag
Go to solution Solved by Carl,

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,


I discovered GSAP over the weekend while trying to complete an animation project. It's supper impressive. I've read the docs over and over and over but I just think I'm missing something or I'm approaching the problem the wrong way.


My goal is to create a rotating Nav. Four block arranged in a circle. Click on a block and they all rotate left until clicked box is at the top. Conceptually simple and I found a nice tutorial on the circle animation in an old forum post for an AS3 code chunk.


So I've created my bezier path and I've create a separate tween for each "button". I use a TweenMax.fromTo progress chunks to offset each button around the curve in my timeline. I've added Labels at each quarter. I just can't figure out how to control the click events on the objects so that the rotate from one label to another correctly. I tried creating a secondary timeline with tweenFromTo chunks to control the first and that failed.


I'm just not sure If I've approached this the right way.


PS. Also you may see that occasionally one of my object will break off from the Bezier and jump to 0,0. If i look at the values being added in the browser(chrome) I see that the other buttons have a 3D transform on them but the broken one has a transform: matrix(1, 0, 0, 1, 0, 0);. What did I do wrong?


I appreciate any advise you can provide. A few days Ago I  didn't think I'd be able to do this at all. Today I feel like I'm on the edge of success thanks to GSAP.



See the Pen EazXYz by gstout (@gstout) on CodePen

  • Like 1
Link to comment
Share on other sites

  • Solution

Hi gstout and welcome to the GreenSock forums,


This is definitely and ambitious first project with GSAP but I have to commend you on your progress. 

You are dabbling in some fairly advanced concepts and actually showing that you understand them quite well.

Really nice.


Also, thanks for the demo. It was very helpful.


I'm pretty sure someone around here will chime in with an even simpler approach, but here's what I came up with:




The tricky part was forcing rotation to always be clockwise, in order to do that I had to make sure I had enough iterations of tweens in the timeline so that I could create a seamless loop. Being the start times are all offset, by 0.25 seconds its important to jump ahead in the timeline from the start to a time where all assets are rendered in their starting position. The basic idea is that a full rotation happens between a time of 1 and 2 seconds, and then again between 2 seconds and 3 seconds.


The timeline will render identically at times of 1 and 2, 1.5 and 2.5, 1.25 and 2.25



So if the current time() is 2.75 and I have to tween to time(2.5), the timeline would tween backwards. However if I subtract 1 second from 2.75, and jump to time(1.75), then I can tween forward to time(2.5)


I know I'm not explaining it as clearly as I could with more time, but hopefully with a little study it makes some sense;)


if you need more details, just let me know.


Again, great job on what you did so far.



edit: 1 more thing. In this case i think using labels is more difficult than just giving each button its own unique time() where it as at the top of the rotation.

  • Like 3
Link to comment
Share on other sites

Thank you so much for this proof of concept!


I had so many ah-ha moments while looking at your solution, I almost ran out of air in my office.


I'm very excited to see that what I wanted to create is possible, and whats more, the other tools in GSAP are inspiring me to conceptualize my site is a ways I had not even dreamed. 


Thank you for your quick response. It made me certain GSAP was the right choice and I've signed up for a membership to help support your work.


All the best,


Link to comment
Share on other sites

Welcome to the club, and thank you!

We couldn't do any of this without members like you.


Glad to know my demo helped. 


Looking forward to seeing what you cook up next.





Link to comment
Share on other sites



I'm hoping you can take a look at this evolution of our last version. Now in the center I have a box that synchs up with the selected.button. Again though I think I'm approach this the wrong way. I created a messageOn and messageOff tween for each box and positioned them just before and at the animation stop points. There are now many adds now to the time line.


You can see, at the start of the animation, for some reason they are all opacity 1. If you run that animation, by clicking on a few boxes, you'll see it self corrects. I have no idea why this happens. You may also notice there is a small jump when rotating to the first item. I'm lost there too.


I'd really appreciate your input. First and for most I'd like this to work as you would expect.  <-- you can stop here and give up on me if you want.


Secondly and more ambitiously, I'd love to understand how to make this start in a running mode. What i mean is have it self animate every so many second to the next item unless someone interacts with it. I know the answer exists in multiple timeline controlling the animations like you have done for the endless loop but I just don't quite get where to begin.


Any advice or help you can provide is very appreciated.


See the Pen gbNovB by gstout (@gstout) on CodePen

Link to comment
Share on other sites

I was able to fix the "all on" at the start problem by switching my message tween to "to" instead of "fromTo",
so this

var message1off = TweenMax.fromTo(".message1", duration*.25, {opacity:1}, {opacity:0});

became this

var message1off = TweenMax.to(".message1", duration*.25, {opacity:0});




I'm almost certain that the flicker only takes place when we use your clever jump to maintain the rotation motion. I don't see why it does not render the 

var message4off = TweenMax.to(".message4", duration*.25, {opacity:0});

which I attached here.

timeline.add(message4off, 1.75)

Seems like it should.


One last thing, you added the below before, Can you explain how this works? What you mean by Global Empty?

//global empty tween to control timeline
var timelineTween = TweenLite.to({}, 0, {})
Link to comment
Share on other sites

hi gstout,


its a little late in the day to wrap my head around everything, but I think the problem with the flash when the loop occurred had to do with the fact that you were trying to add the same tween to the same timeline twice.

A tween can only live in one place or timeline at a time.

It seems you were adding message4off twice, so at 1.75 I just did this


//new from carl
timeline.fromTo(".message4", duration*.25, {opacity:1}, {opacity:0}, 1.75);

timeline.add(message1on, 1.75);
timeline.add(message2on, 2);
timeline.add(message3on, 2.25);
timeline.add(message4on, 2.5);

timeline.add(message1off, 2);
timeline.add(message2off, 2.25);
timeline.add(message3off, 2.5);
timeline.add(message4off, 2.75);





When I saw your first post I was very focused on trying to find a solution to get 4 objects to be synchronized around the same Bezier path, have them all loop and control them from the same timeline. It was a bit of a challenge. In my eagerness to find a solution to that particular problem, I overlooked the fact that getting a dial like this to spin can be done in a much easier fashion.


Please take this demo for a spin: http://codepen.io/chrisgannon/pen/WbMoOK

Spin, the dial and notice how each number stays upright as the dial spins. 

Its just a simple trick of equally spacing the rotation of each number when you create the dial, and then you offset the rotation of each number to compensate for the rotation of the dial as it spins.


Here is a fork that allows you to click on each number to rotate that number clockwise to the top spot.



you could programmatically use the distance to rotate to generate the duration to have constant speed.


on each click you could also call a function that just hides the current message and shows the proper one.


The point here, is that for the functionality you are illustrating, a timeline isn't totally necessary.


Just something to chew on.



Also you mentioned automating the spinning of your menu in intervals.
it would be very possible to create a function that gets called every 4 seconds that advances the timeline a certain amount.

Unfortunately I can't get into in detail now but it would look something like this: http://codepen.io/GreenSock/pen/VYJxYb

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