Jump to content


controling elements in sync with rotational position of different element

Go to solution Solved by GreenSock,

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

Wondering if someone can help shed some light on something I am trying to do with GSAP which I just suspect I am going the wrong way about solving.
Essentially there is a dial that spins for a random amount of 360° rotations and it finally settles on one of 10 segments (each 36° in size). What I am hoping to achieve is the segments to animate as the dial goes past them each time (so in sync with the speed of dial). 
I have very crudely recreated in CodePen, the 3 issues i think I have are:
• I can't get the value returned from updateProps to always be a 0-360° value - it gets higher and higher the more it spins?
• if the dial spins really fast my current way of calling the function segmentGlow() sometimes misses out if the numbers are jumping up in big steps
• i really want the segments to animate each time the dial passes, but I’m not sure if calling the timeline in the function again works
I’m hoping I’m missing out on something and there is a much easier way of solving this….


any pointers/help greatly appreciated

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

Link to comment
Share on other sites

  • Solution

Yeah, it's just a bunch of logic stuff. I noticed a few problems:

  1. In your onUpdate, you were running a bunch of conditional logic on EVERY tick and triggering a glow each and every time based on ranges. That's no good - you only want the number to glow once as the arm swings past it. (at least I assume that's what you want)
  2. You were tweening to values much larger than 360, but your conditional logic assumed all the rotational values would be between 0 and 360. Hint: you can use the modulus operator to convert values like that. 
  3. You were passing the literal string "spinAmount" as a parameter (in onUpdateParams) rather than the actual variable value. It didn't affect your codepen, but I figured I'd point it out because I assume your "real" application depends on that.
  4. It's doing a lot of wasteful DOM lookups - it's better to just cache your "#spinner" as a variable and avoid the lookups on every tick. 
  5. You were setting the transformOrigin redundantly. That's fine, just wasteful. Better to set it once and leave it. 

I forked your codepen and simplified your spinnerMove() function:



Here's that function: 

function spinnerMove(){
  var currAngle = Math.floor(spinner._gsTransform.rotation+2) % 360; //use modulus to keep it between 0 and 360, but add 2 degrees to give things a more natural feel, otherwise it won't light up the final circle until the VERY end of the tween which looks a bit odd because of the easing.
  var i = (prevAngle > 360-36 && currAngle < 360-36) ? 0 : Math.floor(prevAngle / 36) + 1; //if we're looping around (like from 359 to 2), that's a special case and we set i to 0, otherwise just find the closest SMALLER slot. We loop up from there and glow all the slots that are less than the current angle. 
  while (i * 36 <= currAngle) {
  prevAngle = currAngle;

The only other thing I did was add 2 variables toward the top - prevAngle and spinner. I didn't touch the rest of your code. And the code I wrote assumes you're animating forward (increasing rotation), but you could certainly adjust the code to accommodate spinning the other way if you want. I just wanted to get you going in the right direction. 


The theory is that it's recording the previous angle, then after the tween updates it, it looks at the range between those numbers and says "are there any slots between these values? If so, trigger the glow for them." That way, it doesn't matter if you're moving so fast that it flies by 3 slots in one tick - it'll trigger them all appropriately and it won't be wastefully creating a bunch of redundant glow tweens constantly. Then it updates the prevAngle variable and waits for the next update. 


Is that what you were looking for? 

  • Like 4
Link to comment
Share on other sites

Thank you, thank you... you guys are geniuses! It also makes me realise I would never have been able to solve this on my own as I have never heard of modulus!!


I will play with the code and see if I can get a better understanding of what's going on.

  • Like 1
Link to comment
Share on other sites

Actually, I have a quick question:


what did you mean by 


You were setting the transformOrigin redundantly. That's fine, just wasteful. Better to set it once and leave it.


How would I set it just once, do you mean I just need to set it once in the first .to of the TimelineMax? 

Link to comment
Share on other sites

yep , you just need to set transformOrigin once with first tween or with a .set() method

  • Like 1
Link to comment
Share on other sites

With this code, is it possible to make the last segment stay lit/highlighted?


Ive tried working best way of doing this but can't get it to work (JS/code isn't my strongest suit) I assume I'd wrap the tween call (that fades back out) in conditional statement but not sure how to test that it is the final segment in the spinning cycle to set/pass a var.



Link to comment
Share on other sites

thank you so much, you guys make it look so easy!

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