为什么基于 ng-class 的 ng-animate 转换不起作用?
Why is ng-class based ng-animate transition not working?
这是一个非常简化的 ng-class
动画演示,我正在尝试使用过渡实现它。
我正在尝试在选择项目时创建一个简单的淡入淡出动画。
选择一个项目将使用 ng-class
指令在其上添加 selected
class。我正在尝试在 documentation 之后使用 ng-animate
.
添加的动画挂钩 classes 添加过渡效果
下面是我目前的代码。它将 opacity
设置为 0
以及转换 属性,当添加 .selected-add-active
class 时,它应该转换为 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>
为什么我的代码不起作用?
这里的问题似乎是 angular ng-animate 应用 CSS classes 的顺序以及浏览器如何优化 DOM 回流。
ng-animate
在实际添加 class x
之前先添加 x-add
class。这是它强制(或伪造)DOM 回流以便浏览器检测动画的初始状态的地方。
但是由于初始状态的 CSS (.item.selected.selected-add
) 的选择器与尚未添加的 .selected
class 链接在一起,因此它不匹配任何内容浏览器会忽略它。
在此之后,ng-animate
添加 selected
class,然后是 selected-add-active
class。此时初始状态的 CSS 选择器确实匹配,但这些更改发生在同一个回流中,因此浏览器选择从具有最高特异性的选择器应用 opacity
.item.selected.selected-add.selected-add-active {
opacity: 1;
}
现在,由于未检测到元素 opacity
的实际变化,因此不会发生转换。
要解决此问题,请避免将 ng-animate
添加的动画挂钩 class 与正在切换的 class 链接在一起。特别是 x-add
class 应该在应用以下 classes 之前被浏览器检测到。
下面是一个工作示例:
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>
这是一个非常简化的 ng-class
动画演示,我正在尝试使用过渡实现它。
我正在尝试在选择项目时创建一个简单的淡入淡出动画。
选择一个项目将使用 ng-class
指令在其上添加 selected
class。我正在尝试在 documentation 之后使用 ng-animate
.
下面是我目前的代码。它将 opacity
设置为 0
以及转换 属性,当添加 .selected-add-active
class 时,它应该转换为 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>
为什么我的代码不起作用?
这里的问题似乎是 angular ng-animate 应用 CSS classes 的顺序以及浏览器如何优化 DOM 回流。
ng-animate
在实际添加 class x
之前先添加 x-add
class。这是它强制(或伪造)DOM 回流以便浏览器检测动画的初始状态的地方。
但是由于初始状态的 CSS (.item.selected.selected-add
) 的选择器与尚未添加的 .selected
class 链接在一起,因此它不匹配任何内容浏览器会忽略它。
在此之后,ng-animate
添加 selected
class,然后是 selected-add-active
class。此时初始状态的 CSS 选择器确实匹配,但这些更改发生在同一个回流中,因此浏览器选择从具有最高特异性的选择器应用 opacity
.item.selected.selected-add.selected-add-active {
opacity: 1;
}
现在,由于未检测到元素 opacity
的实际变化,因此不会发生转换。
要解决此问题,请避免将 ng-animate
添加的动画挂钩 class 与正在切换的 class 链接在一起。特别是 x-add
class 应该在应用以下 classes 之前被浏览器检测到。
下面是一个工作示例:
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>