为什么基于ng类的ng-animate过渡不起作用?

时间:2016-06-30 13:41:35

标签: javascript css angularjs css3 ng-animate

这是使用我想要实现的转换的ng-class动画的大量简化演示。

我正在尝试在选择项目时创建简单的淡入淡出动画。

选择一个项目将使用selected指令在其上添加ng-class类。我正在尝试在documentation之后添加一个过渡到它,ng-animate添加了动画钩子类。

以下是我到目前为止的代码。它将opacity设置为0以及transition属性,并且当添加.selected-add-active类时,它应该转换为opacity 1.但它不起作用。

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>

为什么我的代码不起作用?

1 个答案:

答案 0 :(得分:4)

这里的问题似乎是角度ng-animate应用CSS类的顺序以及浏览器如何优化DOM重排。

ng-animate最初会在实际添加类x-add之前添加x类。这是强制(或伪造)DOM重排的地方,以便浏览器检测动画的初始状态。

但是由于初始状态的CSS(.item.selected.selected-add)的选择器与.selected类链接,但尚未添加,所以它与任何内容都不匹配,浏览器会忽略它。

在此之后,ng-animate会添加selected类,后跟selected-add-active类。此时初始状态的CSS选择器确实匹配,但这些更改发生在相同的重排中,因此浏览器选择从选择器应用opacity具有最高特异性

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

现在,由于未检测到元素opacity的实际更改,因此不会发生转换。

要解决此问题,请避免链接由ng-animate添加的动画钩子类并切换类。特别是在应用以下类之前浏览器应检测到的x-add类。

以下是一个工作示例:

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>