在AngularJS应用中创建动画,有三种途径:
- 使用CSS3动画
- 使用JavaScript动画
- 使用CSS3过渡
安装
$ bower install --save angular-animate
//引用库
//引用模块
angular.module('myApp', ['ngAnimate']);
它是如何运作的
$animate
服务默认给动画元素的每个动画事件添加了两个CSS类。$animate
服务支持多个内置的指令,它们无需额外的配置即可支持动画。我们可以为自己的指令创建动画。
所有这些预先存在的支持动画的指令,都是通过监控指令上的事件实现的。例如,当一个新的ngView
进入并且把新内容带进浏览器时,这个事件就叫做ngView
的enter
事件。当ngHide
准备显示一个元素的时候,remove
事件就会触发。
下面是指令以及在不同状态触发的事件列表。
$animate
服务基于指令发出的事件来添加特定的样式类。对于结构性的动画(比如进入、移动和离开),添加上去的CSS类是
ng-[EVENT]
和
ng-[EVENT]-active
这样的形式。
对于基于样式类的动画(比如
ngClass
),动画样式类的形式是
[CLASS]-add
、
[CLASS]-addactdive
、
[CLASS]-remove
、
[CLASS]-remove-active
。
最后,对于
ngShow
和
ngHide
,只有
.ng-hide
类会被添加和移除,它的形式跟
ngClass
一样:
.ng-hide-add
、
.ng-hide-add-active
、
.ng-hide-remove
、
.ng-hide-remove-active
。
自动添加类
触发enter
事件的指令会在DOM变更时收到一个.ng-enter
样式类,然后,Angular添加ng-enter-active
类,它会触发动画。ngAnimate
自动检测CSS代码来判定动画什么时候完成。
这个事件完成时,Angular会从DOM元素上移除这两个类,使我们能够在DOM元素上定义动画相关的属性。
如果浏览器不支持CSS过渡或者动画,动画会开始,然后立即结束,DOM会处于最终的状态,不会添加过渡或者动画的样式类。
使用CSS3过渡
要做任何CSS动画,我们都要确认给动画中关注的DOM元素添加了样式。
CSS3过渡是完全基于样式类的,意思是说,只要我们在HTML上定义了动画的样式,这个动画就会在浏览器中动起来。要定义一个动画,我们需要指定想要添加动画的属性,以及特效的持续时间。
.fade-in {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
设置了这个过渡和时间之后,就可以在DOM元素的不同状态上定义属性了。
.fade-in:hover {
width: 300px;
height: 300px;
}
使用ngAnimate
,Angular通过给每个动画事件添加两个样式类的方式开始了我们的指令动画:初始的ng-[EVENT]
类,不久之后是ng-[EVENT]-active
类。
为了自动让上面的DOM元素使用过渡实现Angular动画,我们修改上面初始的.fade-in
示例来包含初始状态类:
.fade-in.ng-enter {
opacity: 0;
}
.fade-in.ng-enter.ng-enter-active {
opacity: 1;
}
也可以把transition
属性放到基准CSS类中。
.fade-in {
-webkit-transition: 2s linear all;
transition: 2s linear all;
}
.fade-in.ng-enter { opacity: 0;}
.fade-in.ng-enter.ng-enter-active { opacity:1;}
.fade-in.ng-leave {opacity: 1;}
.fade-in.ng-leave.ng-leave-active { opacity: 0;}
使用CSS3 动画
使用CSS3动画,我们会用同样的初始样式类ng-[EVENT]
, 但是不需要在ng-[EVENT]-active
状态中定义动画状态,因为CSS规则会处理剩余部分。
我们在@keyframes
规则中创建动画。在@keyframes
规则中定义的CSS元素内部,我们定义要处理的CSS样式。
想让DOM元素动起来时,我们使用animation:
属性来绑定@keyframe
CSS属性,它把动画添加到CSS元素上。
;当在CSS元素上绑定动画时,我们需要同时指定动画的名称和持续时间。如果我们忘记添加动画的持续时间,它默认会设成0,此时动画就不会运行了。
要创建@keyframes
规则,我们需要给关键帧一个名字,并且设置动画的时间阶段,它包含了动画过程中的属性。
@keyframes firstAnimation {
0% {color: yellow;}
100% {color: black;}
}
/*对于Chrome和Safari浏览器 */
@-webkit-keyframes firstAnimation {
from {color: yellow;} //from等于0%
to {color: black;} //from等于100%
}
我们并不局限于0%和100%:可以分步提供动画,比如10%、15%,等等。要把@keyframe
属性赋值到想要应用动画的类上,我们使用animation
关键字,它把动画应用到CSS选择器选定的元素上。
.fade-in:hover {
-webkit-animation: 2s firstAnimation;
animation: 2s firstAnimation;
}
用ngAnimate
,我们把firstAnimation
值绑定到任意用.fade-in
类选定的元素上。Angular自动为我们添加和移除.ng-enter
类,所以我们可以简单地把事件添加到.fade-in.ng-enter
类上。
.fade-in.ng-enter {
-webkit-animation: 2s firstAnimation;
animation: 2s firstAnimation;
}
交错CSS过渡/动画
ngAnimate
捆绑了一个额外的特性,用指定的延迟来间隔同时存在的动画。这意味着如果10个项进入了一个ngRepeat
列表,每个项可以在上一个之后延迟X
毫秒插入。这样产生的特效就是一个交错特效,ngAnimate
把CSS过渡和动画处理成这样。
交错CSS过渡
沿用ng-enter
和ng-enter-active
这样组织CSS过渡代码的格式,可以添加一个额外的CSS类来提供交错延迟。使用下面的CSS代码,可以用CSS过渡来给我们的.fade-in类添加一个交错特效。
.fade-in.ng-enter-stagger {
-webkit-transition-delay:200ms;
transition-delay:200ms;
/* 防止意外CSS继承的保护措施 */
-webkit-transition-duration:0;
transition-duration:0;
}
下面的代码会在每个后续项以动画方式进入之后,执行200毫秒的停顿。注意,另有一个CSS属性指定了持续时间,并且设置成零了。为什么?它在此是一个安全防护,防止意外的CSS继承基础CSS类。要是没有这种保障,交错特效可能就会被忽略了。
但是这对于我们的.fade-in
类意味着什么呢?想象一下我们正在使用一个ngRepeat
元素,这个元素使用的就是.fade-in
类。
Item: #1 -- {{ item }}
每次一系列的项插入到列表中之后,交错延迟会逐步启动。Item #1
会被正常插入,#1
会在200毫秒之后,#3
400毫秒之后,以此类推。
交错CSS动画
CSS动画也支持并且遵循与上面提到的CSS过渡交错特效同样的CSS命名约定。唯一的不同是没有使用transition-delay
,而是用了animation-delay
。如果用CSS动画来实现交错特效,.fade-in
类看上去就会像这样:
.fade-in.ng-enter-stagger {
-webkit-animation-delay:200ms;
animation-delay:200ms;
/* css交错动画需要放在这里 */
-webkit-animation-duration:0;
animation-duration:0;
}
既然CSS关键帧要等到重排(当浏览器重绘屏幕)时才会发生,可能会出现轻微的闪烁,或者元素自身可能短暂地不动,直到交错动画开始生效。这是因为关键帧动画尚未触发,所以from
或者0%
的动画还没有开始。为解决这个问题,在赋值了关键帧动画的CSS类中,可以放额外的CSS样式。
.fade-in.ng-enter {
/* 重排之前的样式 */
opacity:0;
-webkit-animation: 2s firstAnimation;
animation: 2s firstAnimation;
}
.fade-in.ng-enter-stagger { ... }
@keyframes firstAnimation { ... }
@-webkit-keyframes firstAnimation { ... }
什么指令支持交错动画
所有指令都可以,但是仅当同一父容器下的两个或更多相同动画事件同时触发时,才可以使用。所以当10个项被插入一个ngRepeat
列表时,交互特效就产生。这意味着如果ngClass
被放在一个ngRepeat
元素上,ngClass
的值在列表中对每个项都产生了变化,样式类变化的动画就会渲染出一个交错特效。
交错动画也可以在自定义指令中触发。在一行中用$animate
服务调几次,一个交互动画就呈现出来了。确保每个动画的父元素是同一个,并且每个参与动画元素的className
值也是相同的。
使用JavaScript 动画
JS动画不同于前两种Angular动画方法,因为我们直接使用JS设置DOM元素的属性。
所有的主流浏览器都支持JS动画,所以如果想在不支持CSS渐变和动画的浏览器上提供动画的话,这是个好的选择。
这里,我们更新JS来处理动画,而不是操控CSS来让元素动起来。
ngAnimate
在模块API上添加了.animation
方法;这个方法提供了一个接口,我们可以用来创建动画。
animiation()
方法带有两个参数。
- classname(字符串)
这个classname
会匹配要产生动画的元素的class
。 - animateFun(函数)
animate
函数预期会返回一个对象,包含了指令会触发的不同事件函数(当使用的时候)。
angular.module('myApp',['ngAnimate']).animation('.fade-in',function() {
return {
enter: function(element, done) {
// 运行动画
// 当动画结束的时候调用done
return function(cancelled) {
// 关闭或者取消的回调
}
}
}
});
$animate
服务为指定的元素调用这些函数。在这些函数里,我们可以对这个元素做任何事情。唯一要求是在动画结束时,需要调用回调函数done()
。
在这些函数中,我们可以返回一个end
函数,它会在动画结束或者动画被取消时调用。
当动画触发时,$animate
为事件查找匹配的动画函数。如果找到了匹配事件的函数,它会执行这个函数,否则就会完全跳过这个动画。
微调动画
默认情况下,ngAnimate
会自动尝试让每个通过$animate
服务传递过来的元素都动起来。但是不必担心,只有包含了用CSS或者JS动画注册了的CSS类的元素才会真的动起来。
尽管这个系统在运作时,必须检查每个可能的CSS类,这可能会在低速设备上慢一些。ngAnimate
提供了一个配置项,让$animate
提供者可以使用正则表达式对元素进行过滤,以去掉不匹配元素上的动画操作。
myModule.config(function($animateProvider) {
// 唯一合法的参数是正则表达式
$animateProvider.classNameFilter(/\banimate-/);
});
现在有了给定的正则表达式,/animated/
,只有以animate
开始的CSS类会被为动画而处理。结果,我们的.fade-in
动画不会再运行了,它需要被重命名成.animate-fade-in
才能真正运行。
DOM回调事件
当动画在一个元素产生时,我们想要检测DOM操作什么时候发生,可以在$animate
服务上注册一个事件。
element.on('$animate:before', function(evt, animationDetails) {});
element.on('$animate:after', function(evt, animationDetails) {});
内置指令的动画
ngRepeat动画
ngRepeat
指令产生这些事件:
-
{{ r }}
我们的HomeController
默认是这样定义的:
angular.module('myApp',['ngAnimate']).controller('HomeController',
function($scope) {
$scope.roommates = ['Ari', 'Q', 'Sean', 'Anand'];
setTimeout(function() {
$scope.roommates.push('Ginger');
$scope.$apply(); // 触发一次digest
setTimeout(function() {
$scope.roommates.shift();
$scope.$apply(); // 触发digest
}, 2000);
}, 1000);
});
在这些例子中,我们有一个roommates
列表,包含了四个元素。在一秒钟之后,加了第五个。两秒之后,移除了第一个元素。
1.CSS3过渡
要让ngRepeat
列表中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类。
首先,在初始类上定义动画属性:
.fade-in.ng-enter,.fade-in.ng-leave {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。这里,我们把元素从绿色的文字淡入,在进入动画的最终阶段把文字变成黑色。在离开(元素移除)动画中,我们把属性反转:
.fade-in.ng-enter {
opacity: 0;
color: green;
}
.fade-in.ng-enter.ng-enter-active {
opacity: 1;
color: black;
}
.fade-in.ng-leave {}
.fade-in.ng-leave.ng-leave-active {opacity: 0;}
2.CSS3关键帧动画
使用关键帧动画时,无需定义开始和结束的样式类,而是仅定义单个选择器,包含动画样式的键。
首先为关键帧定义动画属性:
@keyframes animateView-enter {
from {opacity:0;}
to {opacity:1;}
}
@-webkit-keyframes animateView-enter {
from {opacity:0;}
to {opacity:1;}
}
@keyframes animateView-leave {
from {opacity: 1;}
to {opacity: 0;}
}
@-webkit-keyframes animateView-leave {
from {opacity: 1;}
to {opacity: 0;}
}
设置了关键帧之后,我们可以简单地把动画附加到ngAnimate
添加的CSS样式类上:
.fade-in.ng-enter {
-webkit-animation: 2s fade-in-enter-animation;
animation: 2s fade-in-enter-animation;
}
.fade-in.ng-leave {
-webkit-animation: 2s fade-in-leave-animation;
animation: 2s fade-in-leave-animation;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义enter
和leave
属性。
angular.module('myApp',['ngAnimate']).animation('.fade-in', function() {
return {
enter: function(element, done) {
// 不使用jQuery的原始动画
// 用jQuery会简单很多
var op = 0, timeout,
animateFn = function() {
op += 10;
element.css('opacity', op/100);
if (op >= 100) {
clearInterval(timeout);
done();
}
};
// 把初始透明度设为0
element.css('opacity', 0);
timeout = setInterval(animateFn, 100);
},
leave: function(element, done) {
var op = 100,timeout,
animateFn = function() {
op-=10;
element.css('opacity', op/100);
if (op <= 0) {
clearInterval(timeout);
done();
}
};
element.css('opacity', 100);
timeout = setInterval(animateFn, 100);
}
}
});
ngView动画
ngView
指令触发这些事件:
Home
Second view
Third view
当跟ng-view
指令协作时,我们是在跟Angular内部的路由打交道。可以把路由设置为:
angular.module('myApp',['ngAnimate', 'ngRoute']).config(function($routeProvider) {
$routeProvider.when('/', {
template: 'One
'
}).when('/two', {
template: 'Two
'
}).when('/three', {
template: 'Three
'
});
})
示例中的三个路由,每个显示了一个不同的视图。
1.CSS3过渡
要让ngView
列表中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类:
.animateView.ng-enter,.animateView.ng-leave {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。这里,我们把元素从绿色的文字淡入,在进入动画的最终阶段把文字变成黑色。在离开(元素移除)动画中,我们把属性反转:
.animateView.ng-enter {
opacity: 0;
color: green;
}
.animateView.ng-enter.ng-enter-active {
opacity: 1;
color: black;
}
.animateView.ng-leave {}
.animateView.ng-leave.ng-leave-active {opacity: 0;}
2.CSS3关键帧动画
首先,添加我们为动画定义的@keyframe
:
@keyframes animateView-enter {
from {opacity:0;}
to {opacity:1;}
}
@-webkit-keyframes animateView-enter {
from {opacity:0;}
to {opacity:1;}
}
@keyframes animateView-leave {
from {opacity: 1;}
to {opacity: 0;}
}
@-webkit-keyframes animateView-leave {
from {opacity: 1;}
to {opacity: 0;}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateView.ng-enter {
-webkit-animation: 2s animateView-enter;
animation: 2s animateView-enter;
}
.animateView.ng-leave {
-webkit-animation: 2s animateView-leave;
animation: 2s animateView-leave;
}
3.JavaScript动画
首先,我们需要下载并且在文档的头部包含jQuery。
当用JS做动画时,需要在动画的描述对象上定义enter
和leave
属性。
angular.module('myApp',['ngAnimate']).animation('.animateView', function() {
return {
enter: function(element, done) {
// 显示如何用jQuery实现动画的例子
// 注意,这需要在HTML中包含jQuery
$(element).css({opacity: 0});
$(element).animate({opacity: 1}, done);
},
leave: function(element, done) {done();}
}
});
ngInclude动画
ngInclude
指令触发这些事件:
我们在页面中包含内联模板,也可以把这些视图设置为从远程服务器获取。
1.CSS3过渡
要让ngInclude
列表中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类:
.animateInclude.ng-enter,.animateInclude.ng-leave {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。这里,我们把元素从绿色的文字淡入,在进入动画的最终阶段把文字变成黑色。在离开(元素移除)动画中,我们把属性反转:
.animateInclude.ng-enter {
opacity: 0;
color: green;
}
.animateInclude.ng-enter.ng-enter-active {
opacity: 1;
color: black;
}
.animateInclude.ng-leave {}
.animateInclude.ng-leave.ng-leave-active {opacity: 0;}
2.CSS3动画
首先,添加为动画定义的@keyframe
:
@keyframes animateInclude-enter {
from {opacity:0;}
to {opacity:1; color: green}
}
@-webkit-keyframes animateInclude-enter {
from {opacity:0;}
to {opacity:1; color: green}
}
@keyframes animateInclude-leave {
from {opacity: 1;}
to {opacity: 0; color: black}
}
@-webkit-keyframes animateInclude-leave {
from {opacity: 1;}
to {opacity: 0; color: black}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateInclude.ng-enter {
-webkit-animation: 2s animateInclude-enter;
animation: 2s animateInclude-enter;
}
.animateInclude.ng-leave {
-webkit-animation: 2s animateInclude-leave;
animation: 2s animateInclude-leave;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义enter
和leave
属性。
angular.module('myApp', ['ngAnimate']).animation('.animateInclude', function() {
return {
enter: function(element, done) {
// 显示如何用jQuery实现动画的例子
// 注意,这需要在HTML中包含jQuery
$(element).css({opacity: 0});
$(element).animate({opacity: 1}, done);
},
leave: function(element, done) {done();}
}
});
ngSwitch动画
ngSwitch
指令触发这些事件:
ngSwitch
指令类似于前面的例子。对于这些例子,我们用下面使用了
ng-switch
指令的HTML来运行:
Home
Second
Home
1.CSS3过渡
要让ngSwitch
列表中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类:
.animateSwitch.ng-enter,.animateSwitch.ng-leave {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。这里,我们把元素从绿色的文字淡入,在进入动画的最终阶段把文字变成黑色。在离开(元素移除)动画中,我们把属性反转:
.animateSwitch.ng-enter {
opacity: 0;
color: green;
}
.animateSwitch.ng-enter.ng-enter-active {
opacity: 1;
color: black;
}
.animateSwitch.ng-leave {}
.animateSwitch.ng-leave.ng-leave-active {opacity: 0;}
2.CSS3动画
首先,添加为动画定义的@keyframe
:
@keyframes animateSwitch-enter {
from {opacity:0;}
to {opacity:1; color: green}
}
@-webkit-keyframes animateSwitch-enter {
from {opacity:0;}
to {opacity:1; color: green}
}
@keyframes animateSwitch-leave {
from {opacity: 1;}
to {opacity: 0; color: black}
}
@-webkit-keyframes animateSwitch-leave {
from {opacity: 1;}
to {opacity: 0; color: black}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateSwitch.ng-enter {
-webkit-animation: 2s animateSwitch-enter;
animation: 2s animateSwitch-enter;
}
.animateSwitch.ng-leave {
-webkit-animation: 2s animateSwitch-leave;
animation: 2s animateSwitch-leave;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义enter
和leave
属性。
angular.module('myApp',['ngAnimate']).animation('.animateSwitch',function() {
return {
enter: function(element, done) {
// 显示如何用jQuery实现动画的例子
// 注意,这需要在HTML中包含jQuery
$(element).css({opacity: 0});
$(element).animate({opacity: 1}, done);
},
leave: function(element, done) {done();}
}
});
ngIf动画
ngIf
指令触发这些事件:
Show me
1.CSS3过渡
要让ngIf中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为
enter和edit状态定义最终状态的类:
.animateNgIf.ng-enter,.animateNgIf.ng-leave {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。这里,我们把元素从绿色的文字淡入,在进入动画的最终阶段把文字变成黑色。在离开(元素移除)动画中,我们把属性反转:
.animateNgIf.ng-enter {
opacity: 0;
color: green;
}
.animateNgIf.ng-enter.ng-enter-active {
opacity: 1;
color: black;
}
.animateNgIf.ng-leave {}
.animateNgIf.ng-leave.ng-leave-active {opacity: 0;}
2.CSS3动画
首先,添加为动画定义的@keyframe
:
@keyframes animateNgIf-enter {
from {opacity:0;}
to {opacity:1;}
}
@-webkit-keyframes animateNgIf-enter {
from {opacity:0;}
to {opacity:1;}
}
@keyframes animateNgIf-leave {
from {opacity: 1;}
to {opacity: 0;}
}
@-webkit-keyframes animateNgIf-leave {
from {opacity: 1;}
to {opacity: 0;}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateNgIf.ng-enter {
-webkit-animation: 2s animateNgIf-enter;
animation: 2s animateNgIf-enter;
}
.animateNgIf.ng-leave {
-webkit-animation: 2s animateNgIf-leave;
animation: 2s animateNgIf-leave;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义enter
和leave
属性。
angular.module('myApp',['ngAnimate']).animation('.animateNgIf', function() {
return {
enter: function(element, done) {
// 显示如何用jQuery实现动画的例子
// 注意,这需要在HTML中包含jQuery
$(element).css({opacity: 0});
$(element).animate({opacity: 1}, done);
},
leave: function(element, done) {done();}
}
});
ngClass动画
当视图中的样式类发生变化时,是可以基于行为去产生动画的。当一个CSS类变更时(比如在ngShow
和ngHide
指令中),$animate
会通知和触发动画,不管是增加了新类,还是移除了旧类。
不同于使用进入动画的命名约定,我们为ngClass
使用一个新的CSS约定,依次为新类加后缀,变为[CLASSNAME]-add
和[CLASSNAME]-remove
。
类似于上面的进入事件,ngAnimate
会在合适的时间为具体的事件添加[CLASSNAME]-addactive
和[CLASSNAME]-remove-active
。
当我们在这些样式类上做动画时,动画先触发,然后最终的类在动画结束时才被添加。当一个类被移除时,它直到动画结束之前都还在元素上。
ngClass
指令触发这些事件:
Grow me
1.CSS3过渡
要让ngClass
中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类:
.animateMe.grown-add,.animateMe.grown-remove {
transition: 2s linear all;
-webkit-transition: 2s linear all;
}
至此,可以简单地在动画中定义初始和最终阶段的CSS属性。
.grown {font-size: 50px;}
.animateMe.grown-add {font-size: 16px;}
.animateMe.grown-add.grown-add-active {font-size: 50px;}
.animateMe.grown-remove {}
.animateMe.grown-remove.grown-remove-active {font-size:16px;}
2.CSS3动画
首先,添加为动画定义的@keyframe
。
@keyframes animateMe-add {
from {font-size: 16px;}
to {font-size: 50px;}
}
@-webkit-keyframes animateMe-add {
from {font-size: 16px;}
to {font-size: 50px;}
}
@keyframes animateMe-remove {
to {font-size: 50px;}
from {font-size: 16px;}
}
@-webkit-keyframes animateMe-remove {
to {font-size: 50px;}
from {font-size: 16px;}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateMe.grown-add {
-webkit-animation: 2s animateMe-add;
animation: 2s animateMe-add;
}
.animateMe.grown-remove {
-webkit-animation: 2s animateMe-remove;
animation: 2s animateMe-remove;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义addClass
和removeClass
属性。
angular.module('myApp',['ngAnimate']).animation('.animateMe', function() {
return {
addClass: function(ele, clsName, done){
// 显示如何用jQuery实现动画的例子
// 注意, 这需要在HTML中包含jQuery
if (clsName === 'grown') {
$(ele).animate({'font-size': '50px'}, 2000, done);
} else { done(); }
},
removeClass: function(ele, clsName, done){
if (clsName === 'grown') {
$(ele).animate({'font-size': '16'}, 2000, done);
} else { done(); }
}
}
});
ngShow/ngHide动画
ngShow
和ngHide
指令在显示或者隐藏元素时,使用了.ng-hide
类。可以在显示和隐藏DOM元素之间的这段时间添加动画。
当在这些样式类上做动画时,动画会先触发,它完成时,最终的.ng-hide
才会被加到DOM元素上。
因为当移除ng-hide
类时,ng-hide
指令还在DOM元素上,所以在它完成之前,我们是看不到动画的。因此,需要告诉CSS把我们的样式类显示出来,不要折叠。
ngShow
和ngHide
指令触发这些事件:
Show me
1.CSS3过渡
要让ngHide
中的元素动起来,我们需要确认添加了展现元素初始状态的CSS样式类,以及为enter
和edit
状态定义最终状态的类:
.animateMe.ng-hide-add,.animateMe.ng-hide-remove {
transition: 2s linear all;
-webkit-transition: 2s linear all;
display: block !important;
}
注意CSS块中的最后一行:它告诉CSS渲染这个类,并且,对于display
属性而言,没有其他备选值。没有这行的话,这个元素就不会显示了。至此,可以简单地在动画中定义初始和最终阶段的CSS属性。
.animateMe.ng-hide-add {opacity: 1;}
.animateMe.ng-hide-add.ng-hide-add-active{opacity: 0;}
.animateMe.ng-hide-remove {opacity: 0;}
.animateMe.ng-hide-remove.ng-hide-remove-active {opacity: 1;}
2.CSS3动画
首先,添加为动画定义的@keyframe
。
@keyframes animateMe-add {
from {opacity: 1;}
to {opacity: 0;}
}
@-webkit-keyframes animateMe-add {
from {opacity: 1;}
to {opacity: 0;}
}
@keyframes animateMe-remove {
from {opacity:0;}
to {opacity:1;}
}
@-webkit-keyframes animateMe-remove {
from {opacity:0;}
to {opacity:1;}
}
为了应用动画,需要做的就是在我们的类中添加动画CSS样式:
.animateMe.ng-hide-add {
-webkit-animation: 2s animateMe-add;
animation: 2s animateMe-add;
}
.animateMe.ng-hide-remove {
-webkit-animation: 2s animateMe-remove;
animation: 2s animateMe-remove;
display: block !important;
}
3.JavaScript动画
当用JS做动画时,需要在动画的描述对象上定义addClass
和removeClass
属性。
angular.module('myApp',['ngAnimate']).animation('.animateMe', function() {
return {
addClass: function(ele, clsName, done){
// 显示如何用jQuery实现动画的例子
// 注意,这需要在HTML中包含jQuery
if (clsName === 'ng-hide') {
$(ele).animate({'opacity': 0}, 2000, done);
} else { done(); }
},
removeClass: function(ele, clsName, done){
if (clsName === 'ng-hide') {
$(ele).css('opacity', 0);
// 强制移除ng-hide类这样我们就可以真的把动画显示出来
$(ele).removeClass('ng-hide');
$(ele).animate({'opacity': 1}, 2000, done);
} else { done(); }
}
}
});
创建自定义动画
$animate
服务给我们在指令中实现自定义动画提供了帮助。把$animate
服务注入到我们自己的应用中之后,可以用暴露出的事件为每个事件触发$animate
对象上的关联函数。
要在我们自己的指令中开始动画,需要注入$animate
服务。
angular.module('myApp',['ngAnimate']).directive('myDirective',
function($animate) {
return {
template: '',
link: function(scope, ele, attrs) {
// 在这里添加动画 例如:
$animate['addClass'](element, 'ng-hide');
}
}
});
至此,就可以把事件绑定到指令上,开始显示我们的动画了。
建立了指令之后,我们可以调用$animate
函数创建一个动画,与我们的指令通信。
angular.module('myApp',['ngAnimate']).animation('.scrollerAnimation',function() {
return {
animateFun: function(element, done) {
// 我们可以在这个函数中做任意想做的事
// 但是需要调用done来让angular知道动画结束了
}
}
});
$animate
服务暴露了一些方法,为内置指令的动画事件提供帮助。这些$animate
服务暴露出来的事件是:enter
、leave
、move
、addClass
、removeClass
。
$animate
服务把这些事件以函数的方式提供,让我们能在自己的指令中处理自定义动画。
addClass()
addClass()
方法触发了一个基于className
变量的自定义动画事件,并且把className
值作为CSS类添加到元素上。当在DOM元素上添加样式类时,$animate
服务给这个className
添加了一个叫-add
的后缀来让我们建立动画。
如果没有CSS过渡,在CSS选择器([className]-add
)上也没有定义关键帧动画,ngAnimate
就不会触发这个动画,只是会把这个样式类加上。
addClass()
方法带三个参数。
- element(jQuery/jqLite元素):正在建立动画的元素。
- className(字符串):正在建立动画,并且添加到元素上的CSS类。
- done(函数):当动画完成时调用的回调函数。
angular.module('myApp',['ngAnimate']).directive('myDirective', function($animate) {
return {
template: '',
link: function(scope, ele, attrs) {
ele.bind('click', function() {
$animate.addClass(ele, 'greenlight');
});
}
}
});
调用addClass()
方法会经过如下步骤:
(1) 运行所有在元素上用JS定义的动画;
(2) [className]-add
类被添加到元素上;
(3) $animate
检查CSS样式来寻找过渡/动画的持续时间和延迟属性;
(4) [className]-add-active
类被添加到元素的classList
中(触发CSS动画);
(5) $animate
用定义过的持续时间等待完成;
(6) 动画结束,$animate
移除两个添加的类:[className]-add
和[className]-add-active
;
(7) className
类被添加到元素上;
(8) 触发done()
回调函数(如果定义了的话)。
removeClass()
removeClass()
方法触发了一个基于className
的自定义动画事件,并且移除在className
值中定义的CSS类。当从DOM元素上移除一个类的时候,$animate
服务给这个className
添加了一个叫-remove
的后缀来让我们建立动画。
如果没有CSS过渡,在CSS选择器([className]-remove
)上也没有定义关键帧动画,ngAnimate
就不会触发这个动画,只是会把这个样式类加上。
removeClass()
方法带三个参数。
- element(jQuery/jqLite元素):正在建立动画的元素。
- className(字符串):正在建立动画,并且从元素上移除的CSS类。
- done(函数):当动画完成时调用的回调函数。
angular.module('myApp',['ngAnimate']).directive('myDirective', function($animate) {
return {
template: '',
link: function(scope, ele, attrs) {
ele.bind('click', function() {
$animate.addClass(ele, 'greenlight');
});
}
}
});
调用·removeClass()·动画方法会经历如下步骤:
(1) 运行所有在元素上用JS定义的动画;
(2) [className]-remove
类被添加到元素上;
(3) $animate
检查CSS样式来寻找过渡/动画的持续时间和延迟属性;
(4) [className]-remove-active
类被添加到元素的classList
中(触发CSS动画);
(5) $animate
用定义过的持续时间等待完成;
(6) 动画结束,$animate
移除三个添加的类:[className]
、[className]-remove
和[className]-remove-active
;
(7) 触发done()
回调函数(如果定义了的话)。
enter()
enter()
方法把元素添加到它在DOM中的父元素,然后运行enter
动画。动画开始之后,$animation
服务会添加ng-enter
和ng-enter-active
类,给指令一个机会来建立动画。
enter()
方法最多可以带四个参数。
- element(jQuery/jqLite元素):正在建立动画的元素。
- parent(jQuery/jqLite元素):这个元素的父元素,它是我们enter动画的焦点。
- after(jQuery/jqLite元素):这个元素的兄弟元素,它将会成为enter动画的焦点。
- done(函数):当动画完成时调用的回调函数。
angular.module('myApp',['ngAnimate']).directive('myDirective',function($animate) {
return {
template: 'Hi
',
link: function(scope, ele, attrs) {
ele.bind('click', function() {
$animate.enter(ele, ele.parent());
});
}
}
});
调用enter()
动画方法会经历如下步骤:
(1) 本元素被插入父元素中,或者是after
元素后面;
(2) $animate
运行所有在元素上用JS定义的动画;
(3) ·.ng-enter·类被添加到元素的classList
中;
(4) $animate
检查CSS样式来寻找过渡/动画的持续时间和延迟属性。
(5) .ng-enter-active
类被添加到元素的classList
中(触发动画);
(6) $animate
用定义过的持续时间等待完成;
(7) 动画结束,$animate
从元素移除.ng-enter
和.ng-enter-active
类;
(8) 触发done()
回调函数(如果定义了的话)。
leave()
leave()
方法运行leave
动画。当它结束运行时,会把元素从DOM移除。动画开始之后,它会在元素上添加.ng-leave
和.ng-leave-active
类。
leave()
方法带两个参数。
- element(jQuery/jqLite元素):正在建立动画的元素。
- done(函数):当动画完成时调用的回调函数。
angular.module('myApp',['ngAnimate']).directive('myDirective',function($animate) {
return {
template: 'Hi
',
link: function(scope, ele, attrs) {
ele.bind('click', function() {
$animate.leave(ele);
});
}
}
});
调用leave()
动画方法会经历如下步骤:
(1) $animate
可运行所有在元素上用JS定义的动画;
(2) .ng-leave
类被添加到元素的classList
中;
(3) $animate
检查CSS样式来寻找过渡/动画的持续时间和延迟属性;
(4) .ng-leave-active
类被添加到元素的classList
中(触发动画);
(5) $animate
用定义过的持续时间等待完成;
(6) 动画结束,$animate
从元素移除.ng-leave
和.ng-leave-active
类;
(7) 元素被从DOM移除;
(8) 触发done()
回调函数(如果定义了的话)。
move()
move()
函数触发move
DOM动画。在动画开始之前,$animate
服务或者把元素插入父容器中,或者直接加到after
元素之后,如果有的话。动画开始后,为了动画的持续,.ng-move
和.ng-move-active
就会被添加。
move()
方法带有四个参数。
- element(jQuery/jqLite元素):正在建立动画的元素。
- parent(jQuery/jqLite元素):这个元素的父元素,它是我们
enter
动画的焦点。 - after(jQuery/jqLite元素):这个元素的兄弟元素,它将会成为
enter
动画的焦点。 - done(函数):当动画完成时调用的回调函数。
angular.module('myApp',['ngAnimate']).directive('myDirective',function($animate) {
return {
template: 'Hi
',
link: function(scope, ele, attrs) {
ele.bind('click', function() {
$animate.move(ele, ele.parent());
});
}
}
});
调用move()
动画方法会经历如下步骤:
(1) 元素被移到父元素中,或者在after
元素之后;
(2) $animate
可运行所有在元素上用JS定义的动画;
(3) .ng-move
类被添加到元素的classList
中;
(4) $animate
检查CSS样式来寻找过渡/动画的持续时间和延迟属性;
(5) .ng-move-active
类被添加到元素的classList
中(触发动画);
(6) $animate
用定义过的持续时间等待完成;
(7) 动画结束,$animate
从元素移除.ng-move
和.ng-move-active
类;
(8) 触发done()
回调函数(如果定义了的话)。
与第三方库集成
Animate.css
要使用这个Animate.css
,从https://github.com/yearofmoo/ngAnimate-animate.css
上下载animate.css
和animate.js
。只需在HTML中引用它们即可。
无需把ngAnimate
当作我们应用的依赖项,只要把ngAnimate-animate.css
当作依赖项包含进来就可以了。这种替代方式能运行,是因为ngAnimate-animate.css
模块默认就请求了ngAnimate
模块。
这个转换做完之后,我们就可以简单地通过ng-class
指令来引用动画类了。