我有一个使用ng-repeat的动态项目列表。当事情发生时,物品可能会消失。我已经使用ng-animate平滑地处理了这些项目的移除动画,但是在它们消失之后,剩下的项目只是简单地捕捉到它们的新位置。我怎样才能顺利地动画这个动作?
我尝试将“全部”转换应用于重复的类并使用ng-move但没有成功。
答案 0 :(得分:19)
您可以通过设置max-height
属性的动画来实现此目的。看看这个样本:
您需要为max-height
选择足够高的值(在我的示例中,我使用了90px)。最初添加项目时,您希望它以0高度开始(我还设置动画left
以使项目从左侧滑入,以及opacity
,但您可以如果他们不同意你正在做的事情,请删除这些:
.repeated-item.ng-enter {
-webkit-transition:0.5s linear all;
-moz-transition:0.5s linear all;
-o-transition:0.5s linear all;
transition:0.5s linear all;
max-height: 0;
opacity: 0;
left: -50px;
}
然后,在ng-enter-active
规则中设置这些属性的最终值:
.repeated-item.ng-enter.ng-enter-active {
max-height: 90px;
opacity: 1;
left: 0;
}
项目删除有点棘手,因为您需要使用基于关键帧的动画。同样,您想要为max-height
设置动画,但这次您希望从90px开始并将其降低到0.当动画运行时,项目将缩小,并且以下所有项目将平滑地向上滑动。 / p>
首先,定义您将使用的动画:
@keyframes my_animation {
from {
max-height: 90px;
opacity: 1;
left: 0;
}
to {
max-height: 0;
opacity: 0;
left: -50px;
}
}
(为简洁起见,我在这里省略了特定于供应商的定义,@-webkit-keyframes
,@-moz-keyframes
等 - 请查看上面的jsfiddle以获取完整的示例。)
然后,声明您将ng-leave
使用此动画,如下所示:
.repeated-item.ng-leave {
-webkit-animation:0.5s my_animation;
-moz-animation:0.5s my_animation;
-o-animation:0.5s my_animation;
animation:0.5s my_animation;
}
<强>基本强>
如果有人在努力弄清楚如何让AngularJS动画完全奏效,这里有一个简略的指南。
首先,要启用动画支持,您需要在加载angular-animate.js
之后添加一个额外的文件angular.js
,。 E.g:
<script type="text/javascript" src="angular-1.2/angular.js"></script>
<script type="text/javascript" src="angular-1.2/angular-animate.js"></script>
接下来,您需要通过将ngAnimate
添加到模块的依赖项列表(在第二个参数中)来加载var myApp = angular.module('myApp', ['ngAnimate']);
:
ng-repeat
然后,为您的repeated-item
项目分配一个班级。您将使用此类名来分配动画。在我的示例中,我使用<li ng-repeat="item in items" class="repeated-item">
作为名称:
repeated-item
然后,您使用ng-enter
类以及Angular添加到的特殊类ng-leave
,ng-move
和{{1}}在CSS中定义动画。添加,删除或移动项目时的项目。
AngularJS动画的官方文档在这里:
答案 1 :(得分:2)
TLDR: Jank不好,用变换做动画。查看this fiddle了解css和演示。
请注意,动画height
,max-height
,top
,......实际上是非常糟糕的表现,因为它们会导致回流,因此会产生更多信息(html5rocks|high-performance-animations更多信息)。
然而,有一种方法是通过利用兄弟选择器来仅使用变换来获得这种类型的动画。
当添加元素时,由于新项目有一次重排,下面的所有项目都会被转换,因此它们会保持在同一位置,然后移除转换以便顺利滑入。
相反,当元素被移除时,它们被转换到新位置以实现平滑滑出,当元素最终被移除时,再次进行一次回流并立即移除变换以使它们保持在其位置(这也是仅transition
设置ng-animate
非常重要的原因。
除了示例之外,您还可以对已删除的项目transform: scaleY(0)
执行transform: translateY()
,并且仅angular.module('app', ['ngAnimate'])
.controller('testCtrl', ['$scope', function($scope) {
var self = this;
self.items = [];
var i = 65;
for(; i < 72; i++)
{
self.items.push({ value: String.fromCharCode(i) });
}
self.addItem = function()
{
self.items.push({ value: String.fromCharCode(i) });
i++;
}
self.removeItemAt = function(index)
{
self.items.splice(index, 1);
}
}])
兄弟姐妹。
请注意,在快速连续删除多个元素时(前一个动画完成之前),此代码段会出现问题。
这可以通过让动画时间比用户删除另一个项目的时间更快或者通过对动画做更多的工作来解决(超出了这个答案的范围)。
注意:显然SO会通过多次删除来破坏演示 - 请查看fiddle以查看其工作情况。
li
{
height: 48px;
width: 300px;
border: 1px solid lightgrey;
background-color: white;
position: relative;
list-style: none;
}
li.ng-enter,
li.ng-enter ~ li {
transform: translateY(-100%);
}
li.ng-enter.ng-enter-active,
li.ng-enter.ng-enter-active ~ li {
transform: translateY(0);
}
li.ng-animate {
z-index: -1;
}
li.ng-animate,
li.ng-animate ~ li {
transition: transform 0.6s;
}
li.ng-leave,
li.ng-leave ~ li {
transform: translateY(0);
}
li.ng-leave.ng-leave-active,
li.ng-leave.ng-leave-active ~ li {
transform: translateY(-100%);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.23/angular-animate.js"></script>
<div ng-app="app" ng-controller="testCtrl as ctrl">
<ul>
<li ng-repeat="item in ctrl.items" ng-bind="item.value">
</li>
</ul>
<button ng-click="ctrl.addItem()">
Add
</button>
<button ng-click="ctrl.removeItemAt(5)">
Remove at 5
</button>
</div>
&#13;
{{1}}&#13;