Jump to content
Search Community

Experiencing with invalidate

RolandSoos 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

Well, first of all I'm sorry that I always have edge cases :)

 

So, I started to experience with invalidate and try to animate properties based on the current responsive ratio. My initial test was great and it worked as expected. 

When you play the Codepen, the code records the current width of the window and on resize it calculates a ratio based on the new value and invalidates the the tweens which need to get invalidated. So the red box will move on a path of a triangle.

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

When the ratio is 1.0 => x:300,y0 -> x:0,y:0 -> x:300,y300 -> x:300,y0

 

When the ratio is 0.5 => x:150,y0 -> x:0,y:0 -> x:150,y150 -> x:150,y0

I was not able to break this example with resize, so I think it works fine :)

 

Example when it fails: I have the same timeline, but the outgoing part will wait for a click event. The timeline is paused until the body receives a click event and then resumed. 

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

 

 

Reproduce the issue: Do not click on the pen, wait until the red box reached the x:0,y:0 position. Currently it waits for the click to happen. Resize the window and the red box will jump on the x axis. Click and the animation continues from the right position.

 

Link to comment
Share on other sites

Thanks @OSUblake, probably you are right. But in that case it should not render anything on invalidate. Here is a simple example:

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

 

 

First x is 100 and it will jump to progress 0.5, so the rendered x is 50. If you click, x will be 200 and it should jump to x:100 as we are the middle of the timeline, but it jumps to 200, to the elements initial value. 

 

Also you are right, changing the playhead position fixes the issue. Maybe it is a feature request, to render the proper value according to the current playhead instead of the initial value. Or create a method which can force the rendering without changing the currently playhead even a little. 

 

Link to comment
Share on other sites

10 minutes ago, RolandSoos said:

But in that case it should not render anything on invalidate.

 

Hm... You're using a fromTo tween, which is like doing a .set() and .to(), so it's changing where it's starting from, and not where it's going.

 

These are tricky scenarios, so maybe @GreenSock can clarify what's going on because I'm not 100% sure.  

  • Like 2
Link to comment
Share on other sites

I checked the source code of GSAP and it turned out that the _time property is set back to 0 on invalidate and when immediateRender is true, it renders the tween's starting point. 

 

Animation.prorotype.invalidate = function() {
  this._time = this._totalTime = 0;
  this._initted = this._gc = false;
  this._rawPrevTime = -1;
  if (this._gc || !this.timeline) {
    this._enabled(true);
  }
  return this;
};


TweenLite.prototype.invalidate = function() {
  if (this._notifyPluginsOfEnabled) {
    TweenLite._onPluginEvent("_onDisable", this);
  }
  this._firstPT = this._overwrittenProps = this._startAt = this._onUpdate = null;
  this._notifyPluginsOfEnabled = this._active = this._lazy = false;
  this._propLookup = (this._targets) ? {} : [];
  Animation.prototype.invalidate.call(this);
  if (this.vars.immediateRender) {
    this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render)
    this.render(Math.min(0, -this._delay)); //in case delay is negative.
  }
  return this;
};

 

Just for a quick try, I slightly modified the invalidate method to force render the tween at the current playHead when invalidate. 

See the Pen EGWwbe?editors=0011 by anon (@anon) on CodePen

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, RolandSoos said:

First x is 100 and it will jump to progress 0.5, so the rendered x is 50. If you click, x will be 200 and it should jump to x:100 as we are the middle of the timeline, but it jumps to 200, to the elements initial value. 

 

One question I have is why this is making of use of a Timeline vs a simple Tween?

 

See the Pen YdZEwq?editors=0010 by sgorneau (@sgorneau) on CodePen

 

Link to comment
Share on other sites

The customised invalidate method didn't end up well. Probably there is a good reason why it renders at position 0. Probably it does not know about its timeline position and the previous tweens on the same element which cause conflicts. I'm not sure if its allowed to use the undocumented render method, but it works fine after the invalidate.

tl.render(tl.time(), null, true);

 

If you do not suggest to use that method, probably I will go with @OSUblake solution, but I think the forced rendering of the current time is more elegant. Also I'm not sure, but increasing the time, might result in rare situations like skipping label or a pause. For example if user drags the browser window which would fire hundreds of resize events... what do you think?

tl.time(tl.time() + 0.00001);

 

Link to comment
Share on other sites

5 minutes ago, RolandSoos said:

Also I'm not sure, but increasing the time, might result in rare situations like skipping label or a pause. For example if user drags the browser window which would fire hundreds of resize events... what do you think?

 

You could move it back.

 

var time = tl.time();
tl.time(time + 0.00001).time(time - 0.00001);

 

  • Like 3
Link to comment
Share on other sites

I wouldn't worry about GSAP. There's a bunch of optimizations under the hood. 

 

Invalidating the tween is the expensive part because it has to recalculate stuff. After that, changing the time would be no different than if the animation where running. And moving the time forward and back is going to happen inside the same frame, so the impact should be minimal.

 

And if somebody is resizing the screen, the browser is already going to be working overtime dealing with layout changes. I don't think anybody expects animations to be running at 60fps when the screen is being resized.

 

  • Like 5
Link to comment
Share on other sites

Some of this has to do with the optimizations for "lazy" rendering (avoiding layout thrashing), but I think I can safely tweak it for this scenario (in the next release). In the mean time, you should be able to just do something like this:

 

var t = tween.time(); //store the current time in a variable
tween.invalidate().time(t); //set it back to that time immediately. 

 

Does that help? 

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

  • 1 month later...

@GreenSock

I have a problem related to this solution. I know we talked about tweens in the original conversation, but since then I started to invalidate the whole timeline.

 

When I have a .set() on the invalidated timeline, the original value will be lost if the timeline gets invalidated after the .set() happened. Example: 

See the Pen gqaEze?editors=0010 by mm00 (@mm00) on CodePen

 The red box will stay visibility:hidden after the invalidate happens at second turn. 

 

I know the logic behind this. Invalidate will force GSAP to read the values again, like it would for a .to() tween. So when the invalidate happens GSAP reads visibility: hidden and it will set that when the timeline restarts.

 

So, as I know the cause, probably I can solve that. I just need to seek back the timeline to the starting position and then invalidate the timeline.

 

var t = timeline.time(); //store the current time in a variable
timeline.time(0); // seek back to position 0 which allow invalidate to read the proper values
timeline.invalidate().time(t); //set it back to that time immediately. 

 

Updated codepen: 

See the Pen yZYrRg?editors=0010 by mm00 (@mm00) on CodePen

 

 

So the question: what do you think, is it fail safe?

 

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