Components: Progress spinner shakes when specifying a diameter.

Created on 12 Jun 2018  路  25Comments  路  Source: angular/components

Bug:

When specifying a diameter (16-32px) on the progress spinner the animation will eventually start to shake by a couple pixels as it animates. Using smaller diameters make it more noticeable. Using other components with animations (material inputs, etc.) makes it worse.

What is the expected behavior?

Progress spinner has a smooth animation that doesn't shake as it animates.

What is the current behavior?

Over time, the progress spinner will begin to shake up and down as it animates.

What are the steps to reproduce?

https://stackblitz.com/edit/angular-material2-issue-xg5xgq

1) Load the stackblitz demo
3) Click on the input (trigger the label animation)
4) Click away from the input (return it to normal)
5) Watch for the progress spinner to shake.
6) The progress spinner animation will never recover.

What is the use-case or motivation for changing an existing behavior?

The issue appears worse the more material components are on the page. Currently, progress spinner is unusable in our app because the shaking is distracting and unpleasant.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular: 6.0.3
Material: 6.2.0
Chrome: Version 67.0.3396.79 (Official Build) (64-bit)

P4 animation materiaprogress-spinner material spec

Most helpful comment

I was able to reproduce it with the example from @cisasteelersfan, but trying out a few quick solutions didn't help (setting the transform-origin in all dimensions, using 3d transforms). Here's an example:

demo

All 25 comments

I am unable to reproduce this issue on a consistent basis. Sometime it shakes and sometimes it looks fine.

@HeathJared I am unable to reproduce the issue that you outlined. Can you confirm if this is still occuring? Unfortunately we have slightly different version of chrome 67.0.3396.99 so I am not sure if maybe this is the difference.

Yes, I just double checked today using the provided Stackblitz link. It's easier to see if you zoom the page in.

I have reproduced it in Chrome Version 67.0.3396.99 (Official Build) (64-bit) and in the latest versions of electron.

It doesn't appear to be happening as frequently at the moment (and much less severe than it was), but here is a quick screen grab that shows it jittering up and down by a pixel or so.

spinner

I've seen it on at least 5 different machines and at it's worse it was described as constantly "vibrating". The GIF does not reflect it's worst, but only what I was able to quickly grab.

We have since removed the progress spinners until it's resolved.

same issue here

Edit:

  • Windows 10
  • Intel HD Graphics 520

@HeathJared I am still unable to reproduce this.

Are you seeing this in other browsers? Additionally, what OSes are you seeing this issue on? Additionally, if you know what GPUs are being used in your reproductions that could prove helpful as well.

I haven't tried any other browser at the moment.
All of the tests were on Windows 10.

I've seen the issue on the following GPUs:

  • GTX 1080
  • GTX 1060
  • GTX 960M
  • GTX 700 series
  • Intel HD Graphics 4000
  • Intel HD Graphics 530

@crisbeto Any chance you would be able to take a look in a Windows 10 environment?

I have a page with multiple spinners that is shaking badly - Stackblitz: https://stackblitz.com/edit/angular-material2-issue-syytap

It still happens when the spinner is placed in a fixed size box.

  • Windows 7
  • Chrome Version 67.0.3396.99 (Official Build) (64-bit)
  • Angular 6.1.1
  • Angular Material 6.4.3
  • Intel HD Graphics 520

I was able to reproduce it with the example from @cisasteelersfan, but trying out a few quick solutions didn't help (setting the transform-origin in all dimensions, using 3d transforms). Here's an example:

demo

Seeing the same "jittery" behaviour, Chrome 68.0.3440.106 on Mac OS 10.13.6. Macbook Pro 2016-model. We're using diameter 20 on the spinners.

However Safari manages to render it flawless, Firefox seems to have minor issues (way more smooth than Chrome, but still seems a bit off).

GPU info:
Radeon Pro 455 2048 MB
Intel HD Graphics 530 1536 MB

Edit: I tried turing GPU Rasterization off, and now it renders perfectly in Chrome;
chrome://flags/#enable-gpu-rasterization

This issue persists to this date.

Still happening for me, it goes away when I zoom into the page

I've looked into this a bit, and it seems that when the spinners are spinning out of sync with one another, the shakiness goes away.

It's easiest to test with just two - StackBlitz

  1. Open up dev tools
  2. Inspect one of the circle elements inside of the svg
  3. Un-Check animation-name property
  4. Re-Check animation-name property

They should now be out of sync with one another, and no longer shaking. Haven't found a fix or workaround for this yet.

*EDIT - So I've created another StackBlitz
I've added a setTimeout and *ngIf on the second spinner to test my theory of them being out of sync. To me, they now look fine (or at least it's _very_ difficult to see shaking). At the very least, this can be used as a hacky work-around for those who have testing teams breathing down their backs 馃槃

We've replaced the material spinner with a one found on codepen:
https://codepen.io/jczimm/details/vEBpoL
MIT licenced (same as all public codepens). Had to do some minor tweaks to it but works just fine for our purposes (watch out as it may not work on IE)

This will not work in firefox (thanks for pointing out @meta72 )

if you dont want to use diameter you can work around it using zoom style property
<mat-spinner style="zoom:0.24"></mat-spinner>

https://stackblitz.com/edit/angular-material2-issue-h47gmt

@tal-abziz sadly, zoom will not work in firefox.
https://www.caniuse.com/#feat=mdn-css_properties_zoom

The following workaround seems to work in Chrome, Firefox, Safari and IE:

.mat-progress-spinner-indeterminate-animation {
  /* keep anim slow to avoid wobble from rounding errors */
  animation-duration: 9s !important;
}

.mat-progress-spinner-indeterminate-animation circle {
  animation-name: progress-spinner-stroke-rotate !important;
  animation-timing-function: linear !important;
  animation-duration: 4s !important;
}

@keyframes progress-spinner-stroke-rotate {
  $start: 200%; /* approx 2/3 of circle circumference */
  $end: 20%;
  0%   { stroke-dashoffset: $start; }
  50%  { stroke-dashoffset: $end; }
  /* removing transform: rotate(720deg) causes wobble */
  100% { stroke-dashoffset: $start; transform: rotate(720deg); }
}

Test here: https://stackblitz.com/edit/angular-material2-rotate-fix

There are multiple problems addressed:

  • The main fix for stroke shaking is to _avoid keyframes without rotation_. Changing 720deg to 0deg causes stroke shaking to reappear. Maybe this is due to outer mat-spinner rotation being countered by inner circle animation keyframes without rotation - I'm not sure.
  • Fix for small wobble in some browsers from outer rotation, likely due to rounding errors. Since main rotation has been moved to inner element, the outer animation now merely masks the pattern, and thus it can be slowed considerably (9s) to make wobble negligible.
  • While the original animation required special keyframes for every diameter, this solution uses percentages (of circle element width) to calculate circle circumference, making the keyframes fit any diameter.

The result is a somewhat different animation but imho still nice - and a bit closer to Chrome's own browser tab spinner.

Having mat-spinner inside mat-card can assist.

.mat-progress-spinner-indeterminate-animation {
/* keep anim slow to avoid wobble from rounding errors */
animation-duration: 9s !important;
}

.mat-progress-spinner-indeterminate-animation circle {
animation-name: progress-spinner-stroke-rotate !important;
animation-timing-function: linear !important;
animation-duration: 4s !important;
}

@keyframes progress-spinner-stroke-rotate {
$start: 200%; /* approx 2/3 of circle circumference /
$end: 20%;
0% { stroke-dashoffset: $start; }
50% { stroke-dashoffset: $end; }
/
removing transform: rotate(720deg) causes wobble */
100% { stroke-dashoffset: $start; transform: rotate(720deg); }
}

I tried this but I get the same behavior. To clarify - do you leave the diameter property on, or remove it?

@blubberbo please check the stackblitz link. Make sure to set ViewEncapsulation.None for styles file or place styles in global styles.scss. Diameter is set. Let me know if demo above works for you.

@blubberbo please check the stackblitz link. Make sure to set ViewEncapsulation.None for styles file or place styles in global styles.scss. Diameter is set. Let me know if demo above works for you.

placing them in the global styles.scss file fixed it, you are a gentleman and a scholar!

@rhartvig I don't get it, your solution is actually breaking the animation, yes it does not flicker, but it does not look like the original animation anymore.

I think it has to be said.

@rhartvig I don't get it, your solution is actually breaking the animation, yes it does not flicker, but it does not look like the original animation anymore.

I think it has to be said.

this is true, it is not the same animation as the original, but not flickering is more important to me. Ideally, it would not flicker and be the original animation. This solution fixed my primary purpose but not a complete fix to the issue

Hello guys, I know it's not always convenient, but you can just hide spinner and show it using opacity property, instead of display property or ngIf, it seems like if you don't change the flow for this component, then it works more or less well. Shaking of top spinner is easily reproduced after quickly clicking on toggle button.
But it doesn't solve the issue completely unfortunately, if I quickly click toggle for the first time, sometimes I can see shaking of the bottom spinner too.
https://stackblitz.com/edit/angular-material2-rotate-fix-uv6ggd

I have commented animation of mat-spinner styles, it is okay.

Was this page helpful?
0 / 5 - 0 ratings