juliangarnier / anime

JavaScript animation engine
https://animejs.com
MIT License
50.42k stars 3.68k forks source link

Scale zero to one values jumps instead of animating #829

Closed EskelCz closed 2 years ago

EskelCz commented 2 years ago

Describe the bug Scale values in 0-1 range are not animating properly.

To Reproduce Steps to reproduce the behavior:

  1. Create an element
  2. Style it to have transform: scale(0)
  3. Run anime({ target: el, opacity: 1, duration: 100 }) Here's the simplest reproduction example: https://stackblitz.com/edit/js-afgrcn?file=index.js (Added translation as well so you can see that anime is running correctly, just not the scale)

Expected behavior Smooth scale animation from 0 to 1

Desktop (please complete the following information):

different55 commented 2 years ago

Opacity does seem to work fine without any issues I could find.

But with scale I do have to either use scale: [0, 1] or scale: "100%" before it behaves properly.

EskelCz commented 2 years ago

@different55 Strange, I've had the issue in my app with opacity as well but now I can't replicate it. Changed the issue to be about the scale only. Thanks for the workaround!

EskelCz commented 2 years ago

Maybe it's because it's not animating based on transform, but a standalone property scale: https://css-tricks.com/almanac/properties/s/scale/ (based on a different system I guess) If so, now I don't know how to animate the transform for 2d scale.

different55 commented 2 years ago

I believe it is using transform, if you remove translateX from your example animation your circle vanishes as anime.js stops overriding the transform value. And if you turn your browser inspector at an animated element, it has both translateX and scale inside the transform property, even when broken.

Diving just a tiny bit deeper into things, it looks like when setting "scale: 1" then the tween has both from and to set to "1". But if you set it to 100%, then from is "0.2777777777777778%". Only scale: [0,1] actually, strictly behaves as it should. Maybe the initial value is somehow being read as some random unit? 0.27778 is 20/72, the kind of number I'd expect from some weird CSS/font unit shuffling.

juliangarnier commented 2 years ago

This is a limitation of anime regarding parsing CSS transforms. Anime will look for inline styles to get pre-defined CSS transforms values, if none has been set, it will use default values (in the case of scale it’s 1). To set the from value to 0, you can either set the scale via js first:

anime.set(el, {scale: 0});

or use the from to array syntax:

anime({
  targets: el,
  scale: [0, 1]
});

I’ve been thinking of adding a more robust way to parse predefined CSS transform values for a while, but the amount of code needed to achieve a solid transform matrix parser is enormous, and I don’t think it’s worth doubling the size of the library for a single use case that is already easily solvable.