Jump to content
Search Community

Is it possible to "cap" a yoyo animation to a percentage of the tween animation?

kursus test
Moderator Tag

Recommended Posts

Hi there,

 

First of all it feels good to be back here! Huge thanks and congrats for GSAP3 which is better than ever. The compressed build size of 50kB is a huge deal for me as it means I can use GSAP in my current project which is awesome.

 

I would like to know if there is a proper way to "cap" a yoyoed tween to a percentage of the animation.

 

Meaning for a given tween gsap.to("#el", { x: '100%', repeat: 3, yoyo: true }) having the yoyo behave just as if the tween was { x: '25%'}

 

I know I could just tweak the tween values myself but it will get unnecessary complex pretty quickly in case of a multi-props tween, so I would like to declare a "100%" tween and just be able to programmatically yoyo cap it to X%.  

 

On the codepen (animation can be replayed by clicking on the text):

- example 1 is the base animation

- example 2 is the base animation with yoyo

- example 3 is the expected behavior (tween values have been "manually" changed to 25% of their value)

- example 4 is an attempt to reproduce example 3 without tweaking the base CSS values (I know the direction is reversed).

 

Thanks a lot for your help.

See the Pen YzyBBrW by jeankev (@jeankev) on CodePen

Link to comment
Share on other sites

1 hour ago, kursus said:

First of all it feels good to be back here! Huge thanks and congrats for GSAP3 which is better than ever.

Welcome back :) 

 

1 hour ago, kursus said:

I would like to know if there is a proper way to "cap" a yoyoed tween to a percentage of the animation.

 

Meaning for a given tween gsap.to("#el", { x: '100%', repeat: 3, yoyo: true }) having the yoyo behave just as if the tween was { x: '25%'}

This sounds like the perfect use case for animating the progress of your animation. Since you have repeats, you should probably use .totalDuration() and .totalProgress() to get the effect that you're wanting. I also included the ability to calculate the values using a given repeat number so if you need more or less repeats you can just change that one variable.

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

 

Keep in mind that the above does it based on 25% of the progress, not the distance. That way it's easily switched out for different values.

Link to comment
Share on other sites

Ah, I think I misunderstood what he was asking for. Good work, Greg :) 

 

Keep in mind that you can use xPercent instead of x: n% and can also leave out the units for the rotation. Also there's not much point in putting a label at the beginning of a timeline - you can just use a position parameter value of 0.

Link to comment
Share on other sites

Thanks, Zach but I'm not convinced I understood correctly either - I just tried to make #2 look like #3 but perhaps I was really only doing the same thing a slightly different way than OP is looking for. 🤷‍♂️

 

It is still good practice for me - I just don't want to lead folks astray too much.

  • Like 1
Link to comment
Share on other sites

Thanks guys for your answers and your interest,

 

@Greg Stager your fromTo has hardcoded reduced values ({ x: "25%", rotateY: "-25deg"}) which is what I want to avoid (else it seems simpler to just modify to).

 

@ZachSaucier Thanks for your tips ! 

 

So to be clear the example 3 is exaclty the expected behavior but I don't want to hardcode reduced values in the base tween (so ideally nothing else than { xPercent:  100,  rotateY: -90} and a 0.25 variable somewhere). I'm pretty sure a modifier would do it ? I'm just worried about the complexity/verbosity induced in general and also to process non Number values (using getUnit() etc) since I have a lot of different effect to manage (and a modifier would imply "redeclaring" CSS properties by hand inside it which could be the cause of errors) .

Link to comment
Share on other sites

5 minutes ago, kursus said:

the example 3 is exaclty the expected behavior but I don't want to hardcode reduced values in the base tween (so ideally nothing else than { xPercent:  100,  rotateY: "-90deg"} and a 0.25 variable somewhere). I'm pretty sure a modifier would do it ? I'm just worried about the complexity induced to process non Number values (using getUnit() etc).

Sure, you could use a modifier to do that:

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

Link to comment
Share on other sites

3 hours ago, ZachSaucier said:

The better method would probably be just to calculate the end values based on the variable

Of course I don't know why I didn't think of that. Thanks a lot 👍

Link to comment
Share on other sites

Thanks for the kind words @ZachSaucier !

 

I think I've found the catch : it is not clearly seen in the example because images have plain background but with this last technique (as with my examples) all from() tweens are not in sync (as they are supposed to always start at 100%). It appears that @Greg Stager had a better understanding of the issue than myself from the beginning 👍 I finally solved it with a fromTo() :

 

tl.to("#img1", 
      {xPercent: -100 * percent, rotationY: 90 * percent, duration: 1, transformOrigin: '100% 50%'}
      , 0)
.fromTo("#img2", 
        {xPercent: 100, rotationY: -90}, 
        {xPercent: 100 * (1-percent), rotationY: -90 * (1-percent), duration: 1, transformOrigin: '0% 50%'}
        , 0)
    

I feel like a "cap" feature would be a nice addition to the core though !

  • Like 1
Link to comment
Share on other sites

Say you have a plain and reusable cube transition like so :

 

const cube = (els: []) => {
        
    const side_a = gsap.fromTo(els[0], {xPercent: 0, rotationY: 0}, {xPercent: -100, rotationY: -90, transformOrigin: '100% 50%'})
    const side_b = gsap.fromTo(els[1], {xPercent: 100, rotationY: 90}, {xPercent: 0,rotationY: 0, transformOrigin: '0% 50%'})
    
    const master = gsap.timeline()
    master.add([side_a, side_b], 0)
    
    return master
}       

For some reason you need to showcase X% of your effect. You could have a convenient method to do so :

 

const tlAttract = cubes($els)
tlAttract.cap(0.2).yoyo(true).repeat(-1)

Right now (maybe I'm doing it wrong) the complexity brought to implement such effect makes your nice transition much harder to understand (notice how side_b to values have been switched to their opposite):

 

See the Pen NWGJMdq by jeankev (@jeankev) on CodePen

 

Link to comment
Share on other sites

We've never had anyone request this feature before so the chances that it would be added to the core are slim at this point, especially given you can implement a solution quite easily like you have. You can adjust the .fromTo tweens to just be .from or .to tweens for simplicity if you'd like depending on the effect you want and how you set it up.

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