Jump to content
Search Community

Modifiers plugin bug?

trsh 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

 

When restart() happens, the element transformations (i believe modified one's) are not reset fully to initial state. So if you watch the very first iteration and compare it's beginning (delayed part) with the next iterations, you can see this is not right. The animations should look the same on the first and all next times restarted.

 

Without plugin 

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

, it works right - can see that the repeated antimon is always 100% (1st and all n times) same.

 

This is a just small example, in a project (like mine) with multiple timelines and values animated, this creates a big mess :(

 

 

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

Link to comment
Share on other sites

Reading _gsTransform values can be a gotcha with the ModifiersPlugin. The x value probably hasn't been updated, so you can use a modulus on the value like this.

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

 

Here's another way you can animate the transformOrigin using a generic object.

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

  • Like 1
Link to comment
Share on other sites

Reading _gsTransform values can be a gotcha with the ModifiersPlugin. The x value probably hasn't been updated, so you can use a modulus on the value like this.

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

 

Here's another way you can animate the transformOrigin using a generic object.

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

 

That's not my problem.

Look carefully at the very start, first delay, when cube stands still.

And look when restarted (in delay phase) , compare.

It's like a diff animations is played.

 

Even you 

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

example still has the problem

Link to comment
Share on other sites

I think it's supposed to behave just as if you separated your fromTo tween into a set and a to tween, like this.

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

 

In my real project "tm.set" is not an option. But will not try to explain that. 

 

 

One small additional question

 

Modifier fires on every update right. It's a overkill for me. I actually need to modify TOrigin once (right before it starts). I tried todo some stuff (update vars in onStart, call updateTo) etc. but non really worked out, and from what I read in forum it should't. Can you advice something? 

Link to comment
Share on other sites

Have you tried using an onStart callback like this?

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

 

But that might lead to other problems depending on how the animation is supposed to look. You might need to also look into using .invalidate() to clear some of the saved values.

http://greensock.com/docs/#/HTML5/GSAP/TweenLite/invalidate/

  • Like 2
Link to comment
Share on other sites

Have you tried using an onStart callback like this?

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

 

But that might lead to other problems depending on how the animation is supposed to look. You might need to also look into using .invalidate() to clear some of the saved values.

http://greensock.com/docs/#/HTML5/GSAP/TweenLite/invalidate/

 

The problem with tm.set, that I would have to manually RESET stuff at some points.., where animated vars on other hand are reset by engine, when, for example, timeline restarts.

 

And I can't change vars & run invalidate in onStart :(. It has effect only on next run.

 

See the Pen qaObEV?editors=0010 by anon (@anon) on CodePen

 

--------------------------------------------------------------------

 

Think I have a type. Will recheck

Edited by trsh
Link to comment
Share on other sites

From what I can tell, this is all expected behavior but I can understand why it might seem odd to you. It looks like it's all related to order-of-operation stuff. Let me see if I can offer some insight...

  1. Inside the tween, each property gets updated and then onUpdate() is called. In your example, it just so happened that transformOrigin was getting updated before "x" in the same tween. That's not a bug - things have to run in some order (iIt's not "wrong" to update the origin after "x" any more so than the other way around). You just wrote your code in a way that assumed x was updated before transformOrigin in the same tween. So when you restart() your timeline, that tween rewound back to its beginning and updated its values. Right before that point, x was 500, and then the tween rendered at its start and set transformOrigin (and called your modifier) and then set x to 0 immediately after that. Notice when your modifier got called, x was still 500 (again, not a bug - it just happened to update the properties in that order). Solution: use an onUpdate() instead of a modifier because the onUpdate() is always called after all properties have been updated (no order-of-operation issues to worry about). Just put a TweenLite.set() in your onUpdate to change the transformOrigin accordingly. 
  2. When you tried putting an invalidate() in an onStart() of your timeline, that didn't work because first the playhead must go back to zero, render as such, and then start (and call your onStart()). Thus, when the playhead returned to 0, the tween rendered at its starting state, setting x back to 0. When you invalidate() the tween, it worked perfectly but remember that x is now at 0, thus when the tween rendered on the next tick, it recorded that as the starting value. All expected behavior. Solution: call invalidate() BEFORE you restart() so that it flushes the recorded start values and uses the current ones instead at that point. 

Hopefully that helps, but if things are still fuzzy, let us know. I'm sure we can find a solution. Like Blake said, it might help to see an example of what you're trying to do exactly. 

 

Happy tweening!

  • Like 3
Link to comment
Share on other sites

Jack. Thanks. I understood it now. About some things:

 

things have to run in some order

 

 

What's the logic for the order. Can I predict/control it some have?

 

So when you restart() your timeline, that tween rewound back to its beginning and updated its values...

 

 

Should be the modifier called on the Rewind update? Does not make a lot sense to me & makes the Rewind process it self kind of unstable (as we can see).

 

Like Blake said, it might help to see an example of what you're trying to do exactly.

 

 

Actually my example is very close to that I wrote at the post beginning. The problems with your suggestions are:

 

1) You suggest a lot TweenLite.set(), but with "set" values doe's not rewind on restart. I would have to handle than manually, and there by over-complicate things. It's cool in a simple example, but in larger project it could get a nightmare.

2) Modifier is an overkill for me (especially with lot logic in it), as I want only push new transformOrigin to from() / once before animation starts.

3) To use invalidate, I would have to catch moment when animation starts, but that's onStart and that's to late.

 

In other words. I want to catch a Tween in timeline, right before from() is set (or if no from - at onstart), and re-init that tween vars, in a manner so I don't have to manually reset on restart. :))

Link to comment
Share on other sites

Hello to add my tweo cents

 

1) You suggest a lot TweenLite.set()

With set() you don't have to use TweenLite or TweenMax but you can use a TimelineMax or TimelineLite instance with set() as well. In your case create another TimelineMax instance and use that instead of what your using now, a TweenMax instance for the var tween

 

Then you can add set() to your child timeline of tween

// have 'tween' var be a TimelineMax instance instead of a TweenMax instance
// then you can chain set() so it is within your 'tween' timeline
var tween = new TimelineMax();

// then chain set() with your fromTo() 
tween
.set()
.fromTo();

set() 4 ways it can be used standalone like you wrote about but also in a timeline

 

Resources:

TimelineMax.set() : http://greensock.com/docs/#/HTML5/GSAP/TimelineMax/set/

TimelineLite.set() : http://greensock.com/docs/#/HTML5/GSAP/TimelineLite/set/

TweenMax.set() : http://greensock.com/docs/#/HTML5/GSAP/TweenMax/set/

TweenLite.set() : http://greensock.com/docs/#/HTML5/GSAP/TweenLite/set/

 

:)

Link to comment
Share on other sites

What's the logic for the order. Can I predict/control it some have?

 

There's a for...in loop that iterates over the properties you provide in the "vars" object, so the order is dictated by how the browser does that loop. My understanding is that there's no spec that determines that, though, so I'm not sure you can rely on it going in a particular order in every browser. For example, {x:100, y:200} might go "x", then "y" in most browsers, but others might do "y", then "x". Feel free to experiment, though.

 

Should be the modifier called on the Rewind update? Does not make a lot sense to me & makes the Rewind process it self kind of unstable (as we can see).

 

Hm. Well, the whole point is that whenever the tween is about to update a value (which it certainly would when you rewind), it feeds that through the modifier. If we changed that behavior and skipped that on rewind, I suspect we'd get a lot of complaints. I guess I can see why you could make an argument for ignoring a modifier when the tween is rendered at exactly a time of 0 (in favor of just plugging in the original recorded values), but I can also see folks getting frustrated with that behavior ("I built a modifier to always intercept values...why is it skipping that every time I rewind?!") 

 

1) You suggest a lot TweenLite.set(), but with "set" values doe's not rewind on restart. I would have to handle than manually, and there by over-complicate things. It's cool in a simple example, but in larger project it could get a nightmare.

 

I read this a few times and still don't quite understand what you mean. I suggested a set() inside of an onUpdate. I can't imagine how or why that'd over-complicate things or be a nightmare in a bigger project. And yes, a set() inside of a timeline does indeed rewind when the playhead goes backward beyond where that set() is. Again, like Blake said, it'd be super helpful to see a reduced test case in codepen or something so that we can better understand the challenges you're running into. All the previous codepens you posted seem to have relatively easy solutions, but it seems like you don't feel like those suffice in your project which may be entirely true but it'd be really helpful to see a demo that shows where/how they're falling short. 

 

2) Modifier is an overkill for me (especially with lot logic in it), as I want only push new transformOrigin to from() / once before animation starts.

 

 

You only want to change it once? Or every time it restarts you want a different value? You should be able to accomplish just about anything - we just need a little demo. You can even invalidate() a set() and change its vars properties if you want. 

 

3) To use invalidate, I would have to catch moment when animation starts, but that's onStart and that's to late.

 

 

Couldn't you just call invalidate() wherever you're calling restart()? I'm struggling to understand why this is a problem, or why it must be inside of an onStart(). 

 

Happy to help, but we'd probably be able to do that much better with a demo, that's all. 

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