AngularJS 1.3 为常用的directives,例如
ngRepeat
,ngSwitch
, 和ngView提供挂钩
,通过$animate
service也可以为自定义的directive使用。 这些animation钩子设置在各种directives的生命周期并处触发animations的地方,它会尝试执行一个CSS 过渡、CSS 关键帧Animation或者 JavaScript 回调Animation (依赖于动画处在特定的directive的位置)。 Animations可以使用vanilla CSS占位, 通过遵循Angular JS设置的命名规定或者被定义为factory的时候通过JavaScript 代码。Animations不可用除非在你的应用里面作为依赖关系包含
ngAnimate
module。下面是一个animations例子,通过
ngShow
和ngHide启用:
index.html
animation.css<div ng-init="checked=true"> <label> <input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible... </label> <div class="check-element sample-show-hide" ng-show="checked" style="clear:both;"> Visible... </div> </div>
.sample-show-hide { padding:10px; border:1px solid black; background:white; } .sample-show-hide { -webkit-transition:all linear 0.5s; transition:all linear 0.5s; } .sample-show-hide.ng-hide { opacity:0; }
参考 API docs for
ngAnimate
关于安装模块的介绍。你也可能也想设置一个独立的 CSS 文件来定义基于CSS的animations。
3)、如何起作用
Angular JS中的Animations完全基于CSS classes。 只有要你有一个附加到你的网站中HTML element中的CSS class,你可以给它应用animations。 例如我们有一个 HTML template,其中有个repeater像这样:
<div ng-repeat="item in items" class="repeated-item"> {{ item.id }} </div>
可以看到,
.repeated-item
class存在于将被重复的element,这个class会被用作引用, 在我们应用的CSS应用 或 JavaScript animation 代码,来告知AngularJS执行一个animation。因为ngRepeat所做的事, 每次一个新子项会被加进列表,ngRepeat 会增加一个
ng-enter
class 名到将被添加的element。 当移除后它会应用ng-leave
class 名,而当围绕它移动的时候会应用一个ng-move
class 名。来看下下面的 CSS code,我们可以看到一些过渡和关键帧动画代码,设置为每个那些事件会当ngRepeat 触发他们时发生:
/* 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代码来对animation同样的操作 (为了执行animations,用到了 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) {} } });
当这些产生了CSS class 名字存在于 element时, AngularJS 自动指出是否执行CSS 或 JavaScript animation。若CSS 和JavaScript animation 代码都存在,并匹配 element上的CSS class 名字,然后 AngularJS 会同时都运行所有animations。
AngularJS也注意到因触发 add 和remove hooks而引起的elements的CSS class变化。这意味着如果一个CSS class 从一个element中添加或移除,然后一个animation会在addition 或removal 之前被执行。(牢记 AngularJS 只能在element中用到了 expression 或者 ng-class directive,才会捕捉 class 变化。)
下面例子展示了怎样在变化中执行animations:
index.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> style.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比下面看到的难一点,但点子是一样的。
少数常用AngularJS directives 支持并触发 animation hooks,只要任何主事件在其生命周期发生。下表详细解释了什么animation事件会被触发。
Directive Supported Animations ngRepeat enter, leave, and move ngView enter and leave ngInclude enter and leave ngSwitch enter and leave ngIf enter and leave ngClass or add and remove ngShow & ngHide add and remove (the ng-hide class value) 每个animation事件中,完整分解的调用步骤,参考 API docs。
Animations 在自定义directives中也能建立在直接注入
$animate
到 directive 基础上,并在需要的时候调用就行。
myModule.directive('my-directive', ['$animate', function($animate) { return function(scope, element, attrs) { element.on('click', function() { if(element.hasClass('clicked')) { $animate.removeClass(element, 'clicked'); } else { $animate.addClass(element, 'clicked'); } }); }; }]);
当内置带structural animations 例如
ngIf
elements到那些类基于animations的elements例如ngClass,
有时在真实动画开始前发生短暂抖动或者在animated element 短暂可见的地方有内容闪烁。为了避免如此,你可以在
ng-[event]-prepare
class应用样式,一旦animation初始化之后就会被添加,但在真实动画开始之前会被移除(等待 $digest过后。 这个class进给 structural animations (enter
,move
,和leave
)添加。这个例子你可能见到抖动:
<div ng-class="{red: myProp}"> <div ng-class="{blue: myProp}"> <div class="message" ng-if="myProp"></div> </div> </div>
可以在
enter
事件中,.message
div 会在动画开始前短暂可见。那个例子,你可以增加样式到CSS,为了确保 element在animation开始前保持隐藏:
.message.ng-enter-prepare { opacity: 0; } /* Other animation styles ... */
关于
$animate每个可用
method的完整分解,参考 API documentation。要看完整演示,参考 animation step within the AngularJS phonecat tutorial。