Jump to content
GreenSock

Edify Technologies

Timeline tweenFromTo not working as expected with yoyo

Go to solution Solved by GreenSock,

Recommended Posts

I'm trying to create a single timeline that uses yoyoEase: true so that it has an elastic.out bounce in both directions. The animation is triggered on click, so I assumed using tl.tweenFromTo() would work. However tweening from 0 to duration / 2, and from duration / 2 to duration seems to just repeat the same animation, as if the yoyo doesn't exist. 

 

On first click I would expect this to run to the end of the initial animation, and on second click to run the yoyo. Is there a better method than tweenFromTo for this?

 

See the Pen dydqbGw by sallf (@sallf) on CodePen

Link to comment
Share on other sites

.tweenFromTo() is for tweening the playhead ("time") of the timeline which does NOT include repeats/yoyos. Think of it this way: if you've got a 3-second timeline, you cannot tween its playhead to a time of 6 because it only has a duration of 3. The playhead can't exceed 3. It looks like you're trying to animate the totalTime() rather than the time(), so you'll have to do that yourself (not using the tweenFromTo() method). It's pretty easy - you can literally animate the "totalTime" property of the timeline, and you'll probably want to use an ease of "none". 

  • Like 1
Link to comment
Share on other sites

@GreenSock thanks! I hadn't wrapped my head around time vs totalTime.

 

I was able to animate totalTime with this:

 

const duration = 3

const tl = gsap.timeline({ 
  paused: true,
  yoyo: true,
  repeat: 1,
})

tl.to('#box', {
  duration,
  xPercent: 100,
  ease: 'elastic.out(1, 0.3)',
  yoyoEase: true,
})

$('#btn').click(() => {
  if (tl.totalTime() === duration) {
    gsap.fromTo(tl, {
      totalTime: duration,
    }, {
      ease: 'none',
      totalTime: duration * 2,
      duration,
    })
  } else {
    gsap.fromTo(tl, {
      totalTime: 0,
    }, {
      ease: 'none',
      duration,
      totalTime: duration,
    })
  }
})

 

This works for the first two clicks, but on the third click, when it should be animating from totalTime 0 to 3 again, it seems to run backwards. I suspect this is because totalTime of 0 & 6 are the same thing and the animation is running in reverse from 6 to 3

 

See the Pen dydqbGw by sallf (@sallf) on CodePen

Link to comment
Share on other sites

I'm having a tough time understanding your question, @Edify Technologies. I'm not seeing anything odd. What am I missing? 

 

Perhaps you're misunderstanding yoyoEase which only flips the ease when the tween is in the yoyo phase? 

 

I have a feeling you may be overcomplicating this a bit - can you describe your real-world goal with this approach? I know (and very much appreciate) that you were only including a very basic minimal demo to isolate the issue. I'd build this effect in a very different way, but before I share that I just wanted to make sure I'm addressing the fundamental issue you're dealing with rather than only focusing on a rework of this minimal demo logic. 

  • Like 1
Link to comment
Share on other sites

@GreenSock I think I've somehow over complicated it too. My real world scenario is pretty basic, I'm trying to make a toggle button that animates to an "on" state using an elastic ease, and then animates to an "off" state with the same elastic ease (not the reverse of that ease, but actually a new ease). I realize I could do something like:

 

const tl = gsap.timeline({ paused: true })

tl
  .addLabel('start')
  .to('#box', { duration: 1, ease: 'elastic.out(1, 0.5)', rotate: '135deg' })
  .addLabel('mid')
  .to('#box', { duration: 1, ease: 'elastic.out(1, 0.5)', rotate: '0deg' }) // back to start position
  .addLabel('end')

// on click, move to "on" state with elastic.out
tl.tweenFromTo('start', 'mid')

// on next click, move to "off" state with elastic.out
tl.tweenFromTo('mid', 'end')

 

However, this method feels heavy handed, since my actual timeline has a bunch of to calls that would need to be copied. I was hoping to find a solution that is a little more DRY. 

 

yoyoEase: true seems to do what I want to do, but it's not working consistently. What you might be missing in my last post is if you press the trigger button three times (wait for the animation to complete between each press) - the first two presses work as expected, but the third press causes the animation to run backwards. It's the `elastic.out` ease in reverse.

Link to comment
Share on other sites

  • Solution

I think this approach would be much simpler: 

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

 

Don't feel like you need to always use timelines. Those are just convenient for when you're trying to choreograph multiple animations. 

 

It should be relatively easy to parameterize things to keep your code DRY. 

 

Does that help? 

  • Like 1
Link to comment
Share on other sites

That's very clean. Super helpful and probably a good shift in how I think about animations. Thanks so much!

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