Why is ng-class based ng-animate transition not working?

。_饼干妹妹 提交于 2019-12-08 06:13:48

问题


This is a heavily simplified demo of ng-class animation using transition that I'm trying to achieve.

I'm trying to create a simple fade in animation when an item is selected.

Selecting an item will add a selected class on it using ng-class directive. I'm trying to add a transition to it following the documentation with the animation hook classes added by ng-animate.

Below is the code I have so far. It sets the opacity to 0 along with the transition property, and when the .selected-add-active class is added it is supposed to transition to opacity 1. But it does not work.

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 {
  background-color: dodgerblue;
}
.item.selected.selected-add {
  transition: opacity 3s;
  opacity: 0;
}
.item.selected.selected-add.selected-add-active {
  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>

Why isn't my code working?


回答1:


The problem here seems to be the order in which angular ng-animate applies the CSS classes and how browser optimizes DOM reflows.

ng-animate initially adds the x-add class prior to actually adding class x. This is where it forces(or fakes) a DOM reflow so that browser detects the initial state for animation.

But since the selector for initial state's CSS (.item.selected.selected-add) is chained with .selected class which isn't added yet, it doesn't match anything and browser ignores it.

After this, ng-animate adds the selected class followed by selected-add-active class. At this point the CSS selector for initial state does match, but these changes happens in the same reflow, hence the browser chooses to apply opacity from the selector with highest specificity which is

.item.selected.selected-add.selected-add-active {
  opacity: 1;
}

Now since no actual change in the element's opacity is detected, no transition takes place.


To fix this, avoid chaining the animation hook classes added by ng-animate with the class being toggled. Especially the x-add class which should be detected by the browser before the following classes gets applied.

Below is a working example:

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 {
  background-color: dodgerblue;
}
.item.selected-add {
  transition: opacity 3s;
  opacity: 0;
}
.item.selected-add.selected-add-active {
  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>


来源:https://stackoverflow.com/questions/38124889/why-is-ng-class-based-ng-animate-transition-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!