Jump to content


Three state button control

Go to solution Solved by ZachSaucier,

Recommended Posts

After watching several hours of tutorials I didn't find answer for my example.

I have a simple timeline for every button with click event attached to every button also.

Animation of the buttons is fine. But animation of "marker" or "slider" that travels x distance

to reach clicked button does not start from current position (unless you always click between

1st and 3rd button). So if, for example, you click on 2nd button, and after that you click on 3rd

button the transition of "marker" element won't happen from 2nd to 3rd button but instead

from 1st button to 3rd button.

I thought that using .to will make animation of target element from current state to desired state

(in this case movement on x axis). What am I doing wrong?


Also - after "marker" moves from certain button to another button,  the color of the letters on the

button should change but I don't know how to target specific button, how to know which button

was "active" before clicking another button. (I solved this with a trick I saw somewhere - turn all colors

to be the same and just change color of the new active button - but what if I want more control over

button that was active before?)


See the Pen VwmGwxo?editors=1011 by hanzek (@hanzek) on CodePen

Link to comment
Share on other sites

Did the demo I showed in your other thread not help you with this project?

See the Pen zJVmMd by PointC (@PointC) on CodePen

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • Solution

Hey girro. Some notes:

  • You're making one of the most common GSAP mistakes of using the old duration parameter instead of including the duration inside of the vars. Putting it in the vars also lets you use defaults.
  • Your repeatRefresh isn't doing anything.
  • If you're going ahead with some ES6 stuff (like arrow functions) you may as well use more features (like using const and let).
  • If you're using a timeline we recommend using the position parameter instead of the delay property.
  • We recommend using the latest GSAP version (3.6.0 at the moment).
  • On CodePen, you should only include the stuff within the body in the HTML section. And you can load external resources via the cog icon next to JS (and CSS).
  • I recommend adding a background rect to each button so that they're easier to click.

As for your question, often times it's good to create animations ahead of time and use control methods (this is one of the tips to animate efficiently). However, if you need the animations to overwrite each other  like this usually it's best to create the animation when you need it. I'd approach it like so:

See the Pen GRNLwXE?editors=0010 by GreenSock (@GreenSock) on CodePen


With that being said, your timelines currently affect both state-specific elements and shared elements (like the background shape). The way I have it set up above, the animation is killed off completely when an item is clicked, which could be an issue if users click between them fast enough. To remedy that, I'd separate the state specific animations from the shared animations. Only kill off the animation(s) related to the shared elements and let the ones for each state continue.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

4 hours ago, PointC said:

Did the demo I showed in your other thread not help you with this project?


I didn't know how to translate html logic to svg element. Here in the example, when you select all <li> elements, you get offsetLeft and width values, and move .slider accordingly. In SVG I didn't know how to select proper element since I needed to select whole group of elements (paths in a group), and the group doesn't have specific width (to automatically reposition .slider element).


Link to comment
Share on other sites

4 hours ago, ZachSaucier said:


Thanks Zach,

this solves my problem. Thans for the notes also.

But I still don't understand why in my example the starting point of the slider would always be initial value (1st button),

and in your example it starts from current position (neither of us specified starting position of  the slider).

Does this have something to do with your events being closed in functions?

Because more or less timelines in my and your example are not that different (minus some of my beginner mistakes).


Link to comment
Share on other sites

My version has all the animations run only on click. So if the end state of the animation when you click the first button doesn't match the initial set up, there will be a difference before and after you click on the first button in the start. There are different ways of dealing with that, but I recommend that you just set the values to what you need them to be at the start.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

27 minutes ago, girro said:

I didn't know how to translate html logic to svg element.

If you use the getBBox() method, you can get the data you need.



Just my two cents, but I'd add a transparent rectangle to the background of those button to make clicking a bit easier. 


Happy tweening.



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