ng-animate with ng-class directive

2020-05-17 08:56发布

问题:

You can use ng-animate with ng-class with the add and remove animations. I'm looking to make one animation in CSS3 but haven't found good examples with ng-class online. So I was wondering if people have good examples they want to share.

I am not sure what my final animation will look like, but for the purpose of this example let's say I just want to make the height of the div gradually increase when I add the class myclass.

 <div ng-class="{{myclass:scopeVar}}" ng-animate="?????"></div>

**CSS**

.myclass.ng-add{??}
.myclass.ng-add-active{??}
.myclass.ng-remove{??}
.myclass.ng-remove-active{??}

回答1:

Animating an ng-class addition or removal using CSS transition has 3 stages. The order of these stages are very important, I almost spent a day figuring out why a simple animation wasn't working due incorrect understanding of the order in which classes are added.

Stage 1:

classname-add/classname-remove class is added.

Unlike what someone might think, this is actually added before the class is added to/removed from the element.

This is the stage where we should add the transition property 1 as well as initial state of our animation.

Stage 2:

classname class is added or removed.

This is where you specify the eventual styles of the element. This class often has nothing to do with our animation. Remember that we are animating the addition/removal of this class. This class itself shouldn't even need to be aware that there is an animation taking place around it.

Stage 3:

classname-add-active/classname-remove-active class is added.

This is added after the class is added to/removed from the element.

This is the stage where we should specify the final state of our animation.


To see this in action, let's create a classic fade-in-out animation shown when an element's selected state changes (selected class change using ng-class).

angular.module('demo', ['ngAnimate'])
  .controller('demoCtrl', function($scope) {
    $scope.selected = false;
    $scope.selectToggle = function() {
      $scope.selected = !$scope.selected;
    };
  });
.item {
  width: 50px;
  height: 50px;
  background: grey;
}
.item.selected {
  /* this is the actual change to the elment
   *  which has nothing to do with the animation
   */
  background-color: dodgerblue;
}
.item.selected-add,
.item.selected-remove {
  /* Here we specify the transition property and
   * initial state of the animation, which is hidden 
   * state having 0 opacity
   */
  opacity: 0;
  transition: opacity 3s;
}
.item.selected-add-active,
.item.selected-remove-active {
  /* Here we specify the final state of the animation,
   * which is visible having 1 opacity
   */
  opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-animate.js"></script>
<div ng-app="demo" ng-controller="demoCtrl">
  <div class="item" ng-class="{selected:selected}"></div>
  <br>
  <br>
  <button ng-click="selectToggle();">
    {{selected? 'Unselect' : 'Select'}}
  </button>
</div>


1 Why should I specify the transition in the first state, instead of just adding it to the class being toggled or a static selector on the element?, you ask.

Well to explain this, assume you need a one-directional animation, for example a fade-out animation when a fade-out class is added.

If you add transition property on the fade-out class itself, the transition stays on the element even after the animation. Which means when your final state (fade-out-add-active) is removed, the element will slowly fade-in back, so we get a fade-out-fade-in which is not what we wanted.

  • Undesired result

  • Desired result



回答2:

I've found a solution to this problem so I thought I'd share it.

http://jsfiddle.net/nicolasmoise/XaL9r/1/

What's nice about this one is that it only requires two CSS classes. You can directly insert the CSS3 transition property into your base class. Unlike other ng-animate cases, I believe all the animations are done in CSS3 (no messing with the DOM like with animations with ng-include etc...).

I want to thank Ilan Frumer for the link to his answer. His solution was for animation with ng-show which is very similar but a little different from animations with ng-class. Hence why I decided to post my example.