Jump to content
Search Community

Feature Request: Wrap values (modulo)

OSUblake test
Moderator Tag

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

Nice work, guys. Yeah, I can certainly see some possibilities with this especially for advanced guys like you two. I'm just curious about how useful it'll be to the majority of the user base out there (if it's worth including/supporting/documenting in the public package). Sometimes I worry that adding things like this might just confuse most of the people out there, and lead them to conclude that GSAP is just for super-advanced animation nerds. Then again, I love making GSAP as insanely flexible as possible so that the possibilities are endless. 


Aside from modulus and custom snapping logic, can you think of any other real-world uses for this? And do you feel strongly one way or the other about including it in the public package (thus documenting and supporting it)? 


I think it would be a good addition, and not because I requested. The only reason I requested the modulus feature is because I've been noticing how people struggle with stuff that has to repeat or cycle. But you came up with something better, a way to transform values without using a getter/setter. I can't tell you how many times I've shown people how to use getters/setters with the same response, "Is there a GSAP way of doing that?"


And I don't think people will be confused by an advanced feature if it's not part of the core functionality. I think most people will judge GSAP by a few key things. Documentation, support, demos, and most importantly, TTFHW (Time To First Hello World). If they can't make a hello world app in a reasonable amount of time, they'll probably move on.

  • Like 1
Link to comment
Share on other sites

Ok, I think I've made enough demos. If you don't get what's going on, the plugin works exactly like a snap/liveSnap function in Draggable. It allows you to modify the value before it gets set, giving you unprecedented amount of control over your tweens.
If you like what you see or think this plugin might be useful, voice your opinion and let Jack know. I can guarantee that if you use GSAP a lot, sooner or later you will need to modify the output of a tween.

  • Like 1
Link to comment
Share on other sites

Ok Blake,


I officially hate you from the bottom of my lungs.


I have spent the whole of last week trying to make one, let me repeat ONE cool animation and I am still not done. In the meantime, you have suggested a new feature, Jack's implemented the idea and you have made who-knows-how-many dozens of different examples.


REALLY? And you say you hold a job? And sleep? No way.


I haven't even had time to look into what you have been showcasing to be honest. But the plugin is really cool and I can see myself coming up with uses to a get/set (once I am a bit more proficient with the concept).


So, *grumble, grumble*, OSUblake is onto something here, Jack.



  • Like 4
  • Haha 1
Link to comment
Share on other sites

If anyone wants to test it out before the official release (which should be very soon), you can: 

ModPropsPlugin: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ModPropsPlugin-latest-beta.js


It requires the next version of TweenMax (or TweenLite) as well: 



If you want to make any suggestions, better do it fast ;) 



Link to comment
Share on other sites

I really like this!


The first thing that popped into my head was elliptical motion:

See the Pen GqOZQz?editors=0010 by pyrografix (@pyrografix) on CodePen


@Jack @Carl I tried the scale property but it didn't work properly though. Any suggestions as to why?

See the Pen QEOPwK?editors=0011 by pyrografix (@pyrografix) on CodePen



I am thinking it is because scale is a composite of scaleX and scaleY. (scaleX and scaleY work independently)

  • Like 1
Link to comment
Share on other sites

That's correct - "scale" is just a convenience property that's an alias for setting scaleX and scaleY. We can't really have ModPropsPlugin accommodate properties like that because it'd be logically impossible to tie them in properly. Like what if you've got scaleX and scaleY that are different, and you also do a "scale" modProps. What exactly would it provide as the value in that case? 


So yes, please use scaleX and scaleY instead of scale. You can point them both at the same function if you want. 

  • Like 2
Link to comment
Share on other sites

Nice example, Elliot! The plugin should make a lot of sense to you since it works a lot like the cycle feature you came up with.


Here's a fork of his demo using scaleX and scaleY...

See the Pen NAXKJZ?editors=0010 by osublake (@osublake) on CodePen


Here's another gotcha I learned today. You can't use roundProps and modProps on the same property as they use the same core mechanisim. So you need to do the rounding in the mod function. Think of roundProps as an easy way to define a modProp that runs Math.round().


If there's still time, here's a couple ideas that might be useful. This one also applies to the new function capability for defining values. Can the index of the target be passed in as parameter like a cycle function?


For modProps, would it possible to define the order in which to call a function, perhaps as comma-delimited string. Using rotation as an example, you might need to calculate an x and y value first. I know that might be hard with transforms as they're applied in a certain order, so I understand why it might not be feasible.

Link to comment
Share on other sites

Yes, Elliot, the "easing" is simply due to how you're applying your logic in the modProps. Think of moving along the x-axis of a sine wave in a completely linear fashion, but watch the y-axis movement. It would appear to easeInOut (slowing down toward the top and bottom, accelerating through the middle). 


As for opacity, yeah, it seems to work fine for me. Did you have trouble with it? 

  • Like 1
Link to comment
Share on other sites

Blake, I just implemented your suggestion for passing the index to the function-based values. First parameter. It's in the latest beta file. And I'm not talking about the modProps functions - I'm talking about regular function-based values. I don't think it's very feasible to pass the index to the modProps functions


As for defining the order in which the modProps should run, no, I don't think that's doable in an efficient enough manner (plus I highly doubt even 0.1% of our users would ever want to tap into that kind of functionality)


Lastly, Carl and I are leaning toward changing "ModPropsPlugin" to simply "ModifyPlugin" because it seems more readable/obvious. Any objections? Other ideas? 

  • Like 1
Link to comment
Share on other sites

Just throwing ideas out there, but it is useful. It gives users the power and convenience of a tween, with the control typically done by manually updating everything using an animation frame request. The problem with doing the updating in an animation frame request is that you have to update every property. With this, you can pick and choose what properties you want to update, the rest are fire-and-forget.


In several of my demos I'm using the mouse position for some of the values, which is probably something you wouldn't do in a real project. I only did that for demo purposes, but the concept stays the same. Check out what happens when you combine my last two demos. You get a nice particle orbiting effect that I've never seen done with SVG.

See the Pen 500e4da20b20c244c2d62132175dc1ea?editors=0010 by osublake (@osublake) on CodePen

  • Like 1
Link to comment
Share on other sites

Just a little FYI ...


I use sine and cosine in a lot of my demos, but understanding how to use them is not as hard as you may think. They produce the same effect, just at different times. If you've ever used Sine.easeInOut, you're doing the same thing!


In fact, you can create circular motion by using Sine.easeInOut. Proof...

See the Pen 76aad24edc0a89f8445dffb968ff8395?editors=0010 by osublake (@osublake) on CodePen


Want elliptical motion? Just use two different values for x and y...

See the Pen 80bbe7f81ab341b2af27a9428860a390?editors=0010 by osublake (@osublake) on CodePen


So what's a Lissajous curve? It happens when sine and cosine aren't synced.



It looks complicated, but you can create that effect using Sine.easeInOut. The only change I made was the time for one of the tweens! Changing the time ratio produces different results.

See the Pen 203596078265e869bc7ff22e95439550?editors=0010 by osublake (@osublake) on CodePen


If you can do all that with a regular tween, than why do you need the plugin? Because you can change some of those properties dynamically, resulting in a totally different looking animation. It's also harder setting something to particular angle/position using a regular tween.

  • Like 6
Link to comment
Share on other sites

I swear you must be reading my mind Blake, I was trying to wrap to wrap my head around how to accomplish both of the techniques you demonstrated recently - the particle trail and the Lissajous curves - then when I saw your pens I thinking a bout how to combine them and you did that too!


I think what interests me most about this plugin is the possibility for building pluggable functions that test for dom conditions and change tween behaviour accordingly. This can do a lot of interesting things for menus and other ui behaviour.


It's been noted that a lot of this could be done with the update handler, maybe so, but this plugin makes it so much easier, or at least it makes it easier for me.

  • Like 1
Link to comment
Share on other sites

Glad you like those examples. That follow the leader pattern should work with any movement, whether it be following the mouse, using Draggable, or being tweened directly. The first element in the chain is the only one that needs to be directed. The rest of the elements are just following the _gsTransform object of the previous element. That's actually what's being passed in as the leader param in the create functions.


You could even modify how they follow, perhaps with some springiness. I see this type of behavior being used a lot in D3.

See the Pen c731fdff203f79de3783ccf578b1e8b6?editors=0010 by osublake (@osublake) on CodePen


It's funny that you brought up reacting to DOM changes. Check out the

See the Pen 74ec33d60b0cf8c5cd6c7a308a69b0af?editors=0010 by osublake (@osublake) on CodePen

I made. If you resize the screen while the ball is bouncing around, it automatically adjusts. I didn't do that intentionally, but I thought it was kind of cool how it automatically adapted to the new screen size.


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