Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CircularProgress, length of the line does not animate under load #10327

Closed
1 task done
henrylearn2rock opened this issue Feb 16, 2018 · 12 comments · Fixed by #13430
Closed
1 task done

CircularProgress, length of the line does not animate under load #10327

henrylearn2rock opened this issue Feb 16, 2018 · 12 comments · Fixed by #13430
Labels
component: CircularProgress The React component component: progress This is the name of the generic UI component, not the React module! good first issue Great for first contributions. Enable to learn the contribution process. hacktoberfest https://hacktoberfest.digitalocean.com/ performance

Comments

@henrylearn2rock
Copy link

henrylearn2rock commented Feb 16, 2018

  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

CircularProgress animation should be smooth and predictable under load

Current Behavior

The animation is okay but the dynamic length of the line only updates once a while under load. Maybe my understanding of Promise is wrong? I thought it would move the load away from the main UI thread?

sept -08-2018 12-00-39

Steps to Reproduce (for bugs)

  1. generate some load inside a promise
  2. observe CircularProgress animation, it still runs but the length of the circle stays constant

demo: https://codesandbox.io/s/j4xvnvv8nv (warning, Chrome pls, firefox crashes under this artificial load)

Context

My app uses canvas to resize a bunch of user selected files. I tried CircularProgress but to my surprise the animation is semi broken. My workaround: animated Gif.

Your Environment

Tech Version
Material-UI v1.0.0-beta.33
React 16.3
browser Chrome
@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 16, 2018

The circular progress animation requires CPU/GPU processing power to run, much more than a simple rotation. I don't think that we could do anything to improve the current situation. It's definitely a limitation. Under heavy load, we lose the stroke dash animation, the only thing that keeps working is the rotation. At least, we rely 100% on CSS to run the animation, some different implementation relies on JS too that makes it less efficient.

Some benchmark on a single frame:

without the dash animation
capture d ecran 2018-02-17 a 00 42 10

with the dash animation
capture d ecran 2018-02-17 a 00 42 41

The performance drawer when disabling the dash animation

capture d ecran 2018-02-17 a 00 41 30

capture d ecran 2018-02-17 a 00 48 01

(the spike of CPU scripting is the hot reloading, the dash animation freeze)

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 16, 2018

@henrylearn2rock My best advise would that you run scripting intensive operations in a web worker or by batch in order not to block the main rendering thread. Also, displaying a single circular progress on the page should cover 90% of the use cases. Don't overuse the component. Maybe we should warn if more than 10 instances are mounted?

@SergeyVolynkin
Copy link

I ran into this problem using Apollo Client Query component, it allows to display different components on different situations (Loading, Error, Success). And when I render CircularProgress on Loading it freezes in an ugly way.

The solution was to remove shrink animation from CircularProgress:

const styles = {
  circleIndeterminate: {
    animation: 'none',
    strokeDasharray: '80px, 200px',
    strokeDashoffset: '0px'
  }
}

const fixedCircularProgress = ({classes}) => <CircularProgress classes={{circleIndeterminate: classes.circleIndeterminate}}/>

export default withStyles(styles)(fixedCircularProgress)

I suggest adding shrinkAnimation prop to the CircularProgress component, so we can use:

<CircularProgress shrinkAnimation={false}/>

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 25, 2018

@SergeyVolynkin Your example can be condensed down to:

export default withStyles({
  circleIndeterminate: {
    animation: 'none',
    strokeDasharray: '80px, 200px',
    strokeDashoffset: '0px'
  }
})(CircularProgress);

Do you have a visual illustration of what's happening?
It would help us evaluate whether it's something worth adding or not in the core.

@SergeyVolynkin
Copy link

SergeyVolynkin commented Oct 25, 2018

@oliviertassinari
Exactly like this one (But just from the start of the component mount):

45252949-df553080-b35e-11e8-9d3c-934f2e959019

Except in my case, the length of the line can become as small as 10px (that's what I describe it as "in an ugly way")

@oliviertassinari
Copy link
Member

@SergeyVolynkin Oh sure, this sounds like a great idea! It's what Facebook is doing:
oct -25-2018 11-49-27

Do you want to open a pull request? :)

@oliviertassinari oliviertassinari added the good first issue Great for first contributions. Enable to learn the contribution process. label Oct 25, 2018
@SergeyVolynkin
Copy link

@oliviertassinari
I'll be able to implement the feature in ~3 weeks, if someone else will not do that.

@oliviertassinari
Copy link
Member

@SergeyVolynkin Awesome :)

@oliviertassinari oliviertassinari added the hacktoberfest https://hacktoberfest.digitalocean.com/ label Oct 27, 2018
@joshwooding
Copy link
Member

joshwooding commented Oct 28, 2018

@oliviertassinari will the shrinkAnimation prop only work on the indeterminate variant?

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 28, 2018

@joshwooding Yes, we can add a warning to ensure that constraint.

@joshwooding
Copy link
Member

@oliviertassinari Is it okay if I work on this?

Do you have a warning in mind? I was thinking:

''Material-UI: you have provided a shrinkAnimation property with a variant other than indeterminate. This will have no effect.''

Also I'm pretty sure I would have to change CircularProgress to a class component to prevent the warning from printing every render. Is this cool?

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 28, 2018

@joshwooding The warning wording is great. Printing the warning at each render isn't great. However, it's something we are already doing. It's a valid option. The alternative is to use the chainPropTypes() helper. You have some example in the codebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: CircularProgress The React component component: progress This is the name of the generic UI component, not the React module! good first issue Great for first contributions. Enable to learn the contribution process. hacktoberfest https://hacktoberfest.digitalocean.com/ performance
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants