pmndrs / react-spring

✌️ A spring physics based React animation library
http://www.react-spring.dev/
MIT License
28.14k stars 1.19k forks source link

Animation is smooth on desktop but slow on Chrome Android #913

Closed Daniel15 closed 3 years ago

Daniel15 commented 4 years ago

🤓 Question

I have an animation that works fine on desktop Firefox and Chrome, but can be quite slow on mobile (tested in Chrome on Android).

To repro, go to https://dnstools.ws/lookup/example.com/A/, wait for it to load, then click the little expand icon to the left of any of the location names.

The code is here: https://github.com/Daniel15/dnstools/blob/master/src/DnsTools.Web/ClientApp/src/components/ExpandTransition.tsx https://github.com/Daniel15/dnstools/blob/master/src/DnsTools.Web/ClientApp/src/components/DnsLookupWorkerResult.tsx#L97

I thought it might be because I'm animating the height of the element, which causes a repaint. However, my code was inspired by the "treeview" example in the react-spring docs (https://codesandbox.io/s/lp80n9z7v9?from-embed), and that example is nice and smooth. I want mine to be smooth like that! Also I tried changing the animation to only do opacity (for testing purposes), and even then it was a bit laggy on mobile.

Any ideas what I'm doing wrong here?

andyfangaf commented 4 years ago

Can confirm this happens on iOS as well.

mbensch commented 4 years ago

I have just discovered that there's a significant performance difference between screens running native resolution and screens running HiDPI mode with pixel scaling. Most phones these days do some sort of fractional scaling to increase sharpness of text, same on Mac Retina displays and 4K or 5K displays run in HiDPI. I'm looking into the issue to get more concrete information but at least that's what I was able to observe so far.

Animation on display without fractional pixel scaling (OSX): animation_fast

Same code on display with fractional pixel scaling (OSX): animation_slow

Tested on 2018 MacBook Pro, 2.9 GHz 6-Core Intel Core i9, 32 GB Ram, Radeon Pro 560X, Firefox 73.0.1

Update: We're seeing the same issue with animations that are not in react-springs and it's significantly worse than animations using react-springs. In our testing Chrome seems not affected by this. We're digging deeper.

CloudBop commented 4 years ago

Hey,

I would like to point out that this is something I came across when animating large amounts of SVG elements. (Demo may come soon....)

Firstly, you should avoid animating anything but opacity and transform...

https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/ https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/ https://www.youtube.com/watch?v=N5EW4HnF6FU

There are quite a few articles across the web on trying to get better performance on mobile browsers. But they all behave differently and different engines so it's kind of tough. CSS properties like translate3d and will-change for better performance. It gets complex.

Super interesting to hear that others have seen performance increases with mobile Zoomed in.

In my case the FPS would be effective zoomed in but get jittery when zoomed out on both iPhone6 some early Android.

The culprit was an opacity attribute on an onClick element. It wasn't even an element that was animating. I changed the opacity attribute to fillOpacity.

I think this is because opacity was effecting both the fill and stroke opacity. I was animating transform: translate() scale() on an element that was a nephew of the onClick element.

Perhaps the renderer figured that as the elements were overlapping that it had to do extra work on the render or something.

It is also possible that if animated CSS properties clash with react-spring then they can drastically increase the workload. IE if you have a class with a css-transition and that is being animated by react-spring....

In my case performance was hugely increased on iPhone6. It is still slowish on 2yr+ old android phones. S7 perhaps. It is rendering inside the SVGDOM so I don't think there any performance gains to be had from CSS properties like will-change/translate3d

React-spring is pretty good though. Degradation in performance doesn't always ruin the experience. In my case when performance does start to take a hit it wouldn't appear obvious unless you knew the original speed of the animation. Only on real old iPads do I see seriously really glitchy problems.

Daniel15 commented 4 years ago

For what it's worth, I switched the site to use regular CSS transitions which helped improve perf quite a bit. https://github.com/Daniel15/dnstools/commit/0e446322334890008a21441f64b8703e65c3bbf9

Manwe-777 commented 4 years ago

Could this be related to CPU clocks/frames somehow? I can repro this on Electron, works fine most of the time but when the PC is under high usage animations become MUCH slower, with less frames and take much longer time to complete, despite of the type of animation i'm using.

kuworking commented 4 years ago

In my case, I see it with useTransition to apply a masonry effect, in an example very similar to the one in the docs

Chrome in desktop fabulous Chrome in Android (Huawei p20 pro) is slow when moving all elements (which are only 10) Chrome in iOS (iPhone 7, much lower resolution) is also slow but experience is way better

To me this is a no-go since I need the experience in mobile as well, and while it is functional, the first impression is too bad