Jump to content
Search Community

GSAP fromTo changes in v3 vs v2?

Zokdok test
Moderator Tag

Recommended Posts

In the setup we have, I've noticed a difference in the fromTo behaviour. Or I might require additional setup now that I missed.

 

In the following situation, the element has a margin left of 0. In the from vars, this value is changed.

gsap.fromTo(
  element,
  0.3,
  {
    marginLeft: -100
  },
  {
    marginLeft: 0,
    ease: Power3.easeInOut,
    clearProps: 'marginLeft'
  }
);

With v2, the marginLeft would be applied immediately, but with v3, I see the element being rendered with marginLeft 0, and the next frame, the from vars are applied and it is moved off screen and then animated in. A form of "Flash of Unstyled Content".

A fix for me is to do the margin left myself before the animation is started, like element.style.marginLeft = '-100px';

And instead of .fromTo doing a .to animation.

But I mainly want to make sure this is/will be the new behaviour or maybe it is a bug!

 

Thanks in advance!

 

Link to comment
Share on other sites

The version I've been using is 3.0.4.

The setup is somewhat more complex, so I'm sorry for being vague, I'm trying to be clear :). The application is working with a virtual dom, rendering is done based on the rAF.

 

I tried to reduce the noise from the following code. So now outside the visible scope, the var projector handles our virtual dom render cycle. When the element is added, this code will be called. It will queue 2 functions, one for measuring the element, one for the animation. The measure is called first, then the animation start.

export let slidePanelInFromLeft = (element: HTMLElement): void => {
  assert(!!element, 'The animation requires an element to animate.');

  let panelWidth: number;

  projector.queueAnimationMeasure(() => {
    panelWidth = element.clientWidth;
  });

  projector.queueAnimationStart(() => {
    gsap.fromTo(
      element,
      0.3,
      {
        marginLeft: -panelWidth
      },
      {
        marginLeft: 0,
        ease: Power3.easeInOut,
        clearProps: 'marginLeft',
        onComplete: projector.scheduleMeasure
      }
    );
  });
};

What I see now is that somehow, 1 render is happening between the placement of the element and the actual start of the animation. If I would be implementing gsap v3 for the first time, I would blame our own vDom rendering, but with v2, this additional frame did not render. Based on some added console.logs, there is no render from the virtual dom happening, all values of panelWidth are correct. Even with a MutationObserver added, I can see it should work all according to plan & code.

So I'm confused why with v2 there is no glitch, and with v3, there is... So that's why I was wondering if changes in the behaviour are made or is this simple a conflicting combination. Meanwhile I'll be trying to pinpoint why this is happening 🧩🥴.

Link to comment
Share on other sites

Hey Zokdok. Thanks for the demo! 

 

We recommend that you use GSAP to set properties like this. I think what's happening is that the element is rendered to the page but since the margin isn't set until the next requestAnimationFrame (GSAP updates things then) it has a flash of the beginning state. @GreenSock can speak to whether or not that's intentional.

 

I'd do it like so:

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

 

Side note, you don't need to (and really shouldn't) use your own requestAnimationFrame encapsulation like you had. It would just make the screen wait an extra animation frame.

Link to comment
Share on other sites

The short answer: that's fixed in the next release which you can preview at https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js

 

Another solution for the current version: add lazy: false to your tween.

 

Explanation: That has to do with a timing issue caused by the fact that you're creating your own requestAnimationFrame loop that's called AFTER GSAP's internal one. By default, as a performance optimization and to avoid layout thrashing, GSAP applies "lazy" rendering meaning that it batches writes at the end of the rendering routine whenever possible. In your case, GSAP already finished its root rendering and THEN you created the tween, so when it deferred rendering it didn't actually kick in until the next requestAnimationFrame. A simple solution would be to set lazy: false on your tween. But again, I've already added logic to the next release that handles this edge case and you wouldn't need to set lazy: false

 

Does that clear things up? 

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

13 hours ago, ZachSaucier said:

Side note, you don't need to (and really shouldn't) use your own requestAnimationFrame encapsulation like you had. It would just make the screen wait an extra animation frame.

In this case I was trying to reproduce how it works with the Virtual Dom framework, normally I wouldn't wrap things in rAFs :).

 

11 hours ago, GreenSock said:

The short answer: that's fixed in the next release which you can preview at https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js

 

Another solution for the current version: add lazy: false to your tween.

[...]

Does that clear things up? 

Thanks for the explanation! I'll wait for the next release, I'm in no rush and will pick it up in my next update dependencies cycle.

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