greensock / GSAP

GSAP (GreenSock Animation Platform), a JavaScript animation library for the modern web
https://gsap.com
19.85k stars 1.72k forks source link

stagger with calc regression during gsap 3 upgrade #330

Closed zslabs closed 4 years ago

zslabs commented 4 years ago

During an upgrade from GSAP 2 to 3.0.1, I noticed a stagger timeline animation I'm running that is using a calc in the initial styles is not working as intended. You can see the diff at https://github.com/zslabs/zslabs.com/compare/feature/gsap3?expand=1#diff-0b059bb579e22b3e7c9021b4bd144909

Here's some screen shots of the DOM before/after the update:

GSAP 2

Screen Shot 2019-11-18 at 9 50 42 PM Screen Shot 2019-11-18 at 9 51 24 PM

GSAP 3.0.1

Screen Shot 2019-11-18 at 9 51 05 PM Screen Shot 2019-11-18 at 9 51 16 PM

The difference here is how the middle element is being animated; with the y transform being set to -50% for some reason.

The default styles that GSAP animates from can be viewed at https://github.com/zslabs/zslabs.com/compare/feature/gsap3?expand=1#diff-0b059bb579e22b3e7c9021b4bd144909R142

When removing the calc, things stagger as intended. Thanks for any help!

ZachSaucier commented 4 years ago

Hey zslabs,

Can you please create a minimal demo of the issue, perhaps in a CodePen, codesandbox, or stackblitz? I tried recreate the issue here but was unable to thus far: https://codepen.io/GreenSock/pen/jOOdEJL?editors=0010

Also, it's generally good to have any transforms also set by GSAP so that GSAP can be fully aware of them. For example adding something like gsap.set(target, {yPercent: -100, y: 30});.

jackdoyle commented 4 years ago

I believe the issue would only show up if the calc() value was in the inline style, not a style sheet declaration. It should be resolved in the upcoming release which can be previewed here: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js

Thanks for pointing this out, @zslabs ! Sorry for the confusion there.

zslabs commented 4 years ago

@jackdoyle Thanks so much for that explanation and really appreciate it as always! GSAP3 is completely blowing my mind btw - congratulations to the entire team 🎉

jackdoyle commented 4 years ago

Should be resolved in the latest release (3.0.2)

zslabs commented 4 years ago

@jackdoyle This is still not working as expected with 3.0.2. https://github.com/zslabs/zslabs.com/tree/feature/gsap3 is the feature branch that can be pulled-down and used.

jackdoyle commented 4 years ago

Oh! I misunderstood your original post, @zslabs. Believe it or not, this is a feature, not a bug (don't slap me).

The fix: Add yPercent:0 to your animation (along with y:0)

The explanation: It's practically impossible for JavaScript to distinguish when the transforms applied to a particular element use % because the browser always reports computed styles in px. So let's say you've got a 200px tall

with a CSS rule of transform: translateY(-50%) - when GSAP tries to discern the current transform, the browser will report it in a matrix() or matrix3d() and the y value will be 100px (percentage is lost). It also loses rotational data because, for example, the matrix for a 0deg rotation is identical to 360deg and 720deg, etc. There are all kinds of ambiguities that creep in when things get shoved into a matrix only.

This is part of the reason why we tell everyone to always set transform-related values through GSAP - it caches the clean values so not only is it faster, but it's always perfectly accurate. Zero loss of rotational data or percentages.

But alas, plenty of people just don't set initial values via GSAP. A very common scenario is for people to set translate(-50%, -50%) to center something, so as a convenience GSAP 3 checks to see if the pixel-based value that the browser provides is EXACTLY -50% and if so, it says "oh, okay, let's automatically set xPercent/yPercent accordingly". In most cases, this is precisely what people would want.

However, in your scenario, it does this and then you animated y to 0 (I'm sure you were thinking it'd get rid of any translateY), but GSAP handles yPercent and xPercent as distinct from y and x which is EXTREMELY convenient in a bunch of scenarios (I won't bore you here with an explanation).

In short, your initial translateY(-50%) was influencing GSAP 3 to apply yPercent:-50 which stayed there when you only animated "y". Again, all you need to do is set yPercent to 0 and you'll be golden.

Of course I'd still recommend setting even your initial values via GSAP so that you can 100% rely on everything being perfect with no ambiguities. It's fine to set things in CSS initially if you're trying to avoid the initial flash of unstyled content, but you could ALSO gsap.set() it.

Does that clarify things?

zslabs commented 4 years ago

@jackdoyle It does! Thank you very much for the detailed explanation. I know you are always dealing with all the different subtleties of how a browser interprets styling, and you digging in to "why" this is happening was extremely enjoyable to read through. Thank you again and I hope you have a great day!