pre:本文翻译自官方文档,AngularJS版本为v1.3.0-beta.8。欢迎分享,转载请注明。
Animations
AngularJS自1.2版本起,可以在一些常用的directive上绑定animation,比如ngRepeat, ngSwitch和ngView,也可以在自定义的directive上绑定animation(使用$animation)。在使用了某些directives的元素的生命周期中,能够通过一些animation的钩子来触发animation事件,当触发时,会表现出动画效果(动画效果通过css或javascript定义)。可以使用纯css(遵循AngularJS中的一些规范)或者javascript代码(定义在服务中)来设置animation。
使用Animation前,需要在你的应用中添加对ngAnimate Module的依赖。
下面是一个对ng-show或ng-hide元素使用animation的示例:
安装
安装说明请查阅ngAnimate的API文档
You may also want to setup a CSS file for defining CSS-based animations
原理
Animation在angular中完全基于css。只要为元素添加一个css类型,就可以在此元素上应用animation。例如,有一个html模板(模板中使用了ng-repeat):
html:
<div ng-repeat="item in items" class="repeated-item"> {{ item.id }} </div>
css:
.sample-show-hide { padding:10px; border:1px solid black; background:white; } .sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove { -webkit-transition:all linear 0.5s; -moz-transition:all linear 0.5s; -o-transition:all linear 0.5s; transition:all linear 0.5s; display:block!important; } .sample-show-hide.ng-hide-add.ng-hide-add-active, .sample-show-hide.ng-hide-remove { opacity:0; } .sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove.ng-hide-remove-active { opacity:1; }
模板中的div元素将被复制,并且每个div元素具有"repeated-item"类,可以通过基于这个类添加css和/或javascript代码,来通知angular为次模板增加动画效果。
在此使用ng-repeat的模板中,当在items中新增一项时,ngRepeat会为新产生的元素添加一个ng-enter类;当删除一项时会为将被删除的元素添加一个ng-leave类,当元素交换位置时,回为响应元素添加ng-move类。
通过以下css代码,我们可以看到,当ngRepeat的相应事件被触发时,为这些事件绑定的transition和keyframe animation代码。
/* We're using CSS transitions for when the enter and move events are triggered for the element that has the .repeated-item class */ .repeated-item.ng-enter, .repeated-item.ng-move { -webkit-transition:0.5s linear all; -moz-transition:0.5s linear all; -o-transition:0.5s linear all; transition:0.5s linear all; opacity:0; } /* The ng-enter-active and ng-move-active are where the transition destination properties are set so that the animation knows what to animate. */ .repeated-item.ng-enter.ng-enter-active, .repeated-item.ng-move.ng-move-active { opacity:1; } /* We're using CSS keyframe animations for when the leave event is triggered for the element that has the .repeated-item class */ .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; } @keyframes my_animation { from { opacity:1; } to { opacity:0; } } /* Unfortunately each browser vendor requires its own definition of keyframe animation code... */ @-webkit-keyframes my_animation { from { opacity:1; } to { opacity:0; } } @-moz-keyframes my_animation { from { opacity:1; } to { opacity:0; } } @-o-keyframes my_animation { from { opacity:1; } to { opacity:0; } }
使用javascript可以实现相同的动画效果(使用JQuery实现动画效果)
myModule.animation('.repeated-item', function() { return { enter : function(element, done) { element.css('opacity',0); jQuery(element).animate({ opacity: 1 }, done); // optional onDone or onCancel callback // function to handle any post-animation // cleanup operations return function(isCancelled) { if(isCancelled) { jQuery(element).stop(); } } }, leave : function(element, done) { element.css('opacity', 1); jQuery(element).animate({ opacity: 0 }, done); // optional onDone or onCancel callback // function to handle any post-animation // cleanup operations return function(isCancelled) { if(isCancelled) { jQuery(element).stop(); } } }, move : function(element, done) { element.css('opacity', 0); jQuery(element).animate({ opacity: 1 }, done); // optional onDone or onCancel callback // function to handle any post-animation // cleanup operations return function(isCancelled) { if(isCancelled) { jQuery(element).stop(); } } }, // you can also capture these animation events addClass : function(element, className, done) {}, removeClass : function(element, className, done) {} } });
通过在元素上生成的类名,AngularJS能够自动判断是否添加css或者javascript动画。如果为一个元素同时定义了css动画和javascript动画,则AngularJS会同时执行这两个动画。
class和ngClass动画绑定
当元素的类(class)发生变化时,angular可以通过触发绑定的add和remove来添加动画效果。这句话的意思是,当一个元素绑定或删除某个class时,在该class被添加或移除的过程中,AngularJS可以触发响应的动画效果(注意:AngularJS只能捕获到通过表达式或ng-class改变的class)
html:
<p> <input type="button" value="set" ng-click="myCssVar='css-class'"> <input type="button" value="clear" ng-click="myCssVar=''"> <br> <span ng-class="myCssVar">CSS-Animated Text</span> </p>
css:
.css-class-add, .css-class-remove { -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; } .css-class, .css-class-add.css-class-add-active { color: red; font-size:3em; } .css-class-remove.css-class-remove-active { font-size:1.0em; color:black; }
尽管这里的css和我们平时看到的有些不同,但是概念是一样的。
哪些指令(directive)支持animation?
一少部分常用的directives在它们的生命周期中,任何时间都支持并能够触发animation绑定。具体信息见下表
指令(directive) | 支持的动画绑定事件 |
ngRepeat | enter, leave and move |
ngView | enter and leave |
ngInclude | enter and leave |
ngSwitch | enter and leave |
ngIf | enter and leave |
ngClass or | enter and remove |
ngShow&ngHide | enter and remove |
更详细的内容见API文档
在自定义的directives中使用animation
自定义的directives中使用animation,只需将$animation注入到自定义directives中,在需要是调用即可。
myModule.directive('my-directive', ['$animate', function($animate) { return function(element, scope, attrs) { element.on('click', function() { if(element.hasClass('clicked')) { $animate.removeClass(element, 'clicked'); } else { $animate.addClass(element, 'clicked'); } }); }; }]);
更多
$animation 详细api文档:https://code.angularjs.org/1.3.0-beta.8/docs/api/ngAnimate/service/$animate
demo:https://code.angularjs.org/1.3.0-beta.8/docs/tutorial/step_12