6

I've noticed that with ngAnimate loaded CSS transitions are "jerky" on Chrome when interrupted with another transition. That is, they seem to jump ahead to the target state, rather than start from the current value. The exact same transitions are much smoother without ngAnimate loaded, and smoother on Firefox with/without ngAnimate.

For example, a simple element that adds/removes a class on click:

<bigger-on-click-class class="{{showBigger ? 'bigger' : ''}}" ng-click="showBigger = !showBigger"></bigger-on-click-class>

animated by the CSS transition:

bigger-on-click-class {
  display: block;
  height: 200px;
  width: 200px;
  background: red;
  -webkit-transition: height 5s;
  transition: height 5s;
}

bigger-on-click-class.bigger {
  height: 400px;
}

behaves differently on multiple clicks in quick succession, depending on whether ngAnimate is loaded:

http://plnkr.co/edit/Fhwbd3WRiz5wHRIm10y3?p=preview without ngAnimate http://plnkr.co/edit/WSED064MV2dtPnsEQuti?p=preview with ngAnimate

If you try clicking quickly multiple times on the red boxes in the previous examples, you should see what I mean, or click below to view a screencast.

asdffsda

Other than not loading ngAnimate, is there a way to avoid this, so interrupting animations start from the currently displayed value/position?

Edit: the initial links were incorrect. Also, the jerky behaviour is observed in Chrome, but not Firefox. Edit: reframed the question to make it clearer it's a Chrome/Firefox difference

Michal Charemza
  • 25,940
  • 14
  • 98
  • 165
  • What device are you using ? – Nix Apr 18 '14 at 15:00
  • I'm using Chrome on a mac. – Michal Charemza Apr 18 '14 at 15:13
  • I dont see it. I'm using Chrome/Mac. – Nix Apr 18 '14 at 15:17
  • Have you tried using ng-class="{'bigger': showBigger}" instead of text binding inside of the class attribute? – Brocco Apr 18 '14 at 15:45
  • I've just realised: I accidentally posted the same Plunkr twice. One of them should not have ngAnimate loaded, and the other should. Can edit it in an hour or so (or someone else, feel free...) – Michal Charemza Apr 18 '14 at 16:06
  • Links have been fixed, as well as some semi-broken CSS. I've also noticed that the behaviour of jerky animation does not occur on Firefox. – Michal Charemza Apr 18 '14 at 16:58
  • @Brocco Yes, and same jerky effect on Chrome http://plnkr.co/edit/oIYvnS3G30OrMGiVlwJf?p=preview – Michal Charemza Apr 28 '14 at 05:02
  • Based upon the chrome dev tools timeline/frames this animation is WELL above 60 fps for the entire duration of the animation. You're moving 200px across 5 seconds, which is a small distance over a long time and pixels are only so big. Also I really didn't notice any jerkiness during the animation (Chrome v34) – Brocco Apr 28 '14 at 13:07
  • @Brocco the jerkiness visible when it the transition is interrupted. In my examples, by clicking again on the box. – Michal Charemza Apr 28 '14 at 13:12

3 Answers3

8

I noticed when the animation occurs the style is being set to:

transition: none;
-webkit-transition: none;

I assume ngAnimate sets these style properties during it's processing and the other browsers are unaffected by them during the brief moment they are set but when chrome sees them it immediately completes the animation as though no transition was applied.

So to fix your problem you just need to ensure these properties get ignored by setting your properties as !important:

transition: height 5s !important;
-webkit-transition: height 5s !important;

Which can be seen working in the plnkr here

Theo
  • 1,252
  • 17
  • 23
  • 1
    Thanks! Although it seems quite a deliberate thing to set the transition to none. Do you know why this might be, or what the consequences would be setting `!important` on the transitions to override this? – Michal Charemza Apr 28 '14 at 18:36
  • You make a good point. I had a look at the source code and couldn't see any obvious reasons they have done it. Maybe they just wanted to ensure each animation always started from the beginning. I can't imagine that setting !important on the transition will have any meaningful consequences though. If it is a concern you could always use an animation instead of a transition. – Theo Apr 28 '14 at 19:32
4

One way of avoiding the jerkiness: upgrade to Angular 1.3. To quote Angular 1.3 beta 7 ngAnimate docs

Earlier versions of ngAnimate may have caused natural CSS transitions to break and not render properly due to $animate temporarily blocking transitions using 0s none

And the difference can be seen in my Plunker using Angular 1.3 beta 7

Michal Charemza
  • 25,940
  • 14
  • 98
  • 165
  • This is a better answer because the older beta versions of Angular 1.3 not only caused jerky animations but they caused some weird paint issues in certain scenarios. – David Myers May 23 '14 at 18:08
2

In my case the problem was because ng-hide css class was set to display:none and the animation didn't work in chrome, but it works in safari.

RobertKru
  • 21
  • 5