AngularJS中ngAnimate模塊支持動畫效果,但是ngAnimate模塊並未包含在AngularJS核心庫中,因此需要使用ngAnimate需要在定義Module時聲明對其的引用。
AngularJS中實現動畫效果有兩大種方式:
官方給出的能支持動畫效果的Directives:
示例1(官方Demo):
1 <!DOCTYPE>
2 <html>
3 <head>
4 <style type="text/css">
5 /* 開始時的樣式 */
6 .fade.ng-enter {
7 transition: 5s linear all; /* 當使用css transition實現動畫效果時,在開始時的樣式中必須包含transition的設置 */
8 opacity: 0;
9 }
10
11 /* 結束時的樣式 */
12 .fade.ng-enter.ng-enter-active {
13 opacity: 1;
14 }
15 </style>
16
17 <script src="/Scripts/angular.js"></script>
18 <script src="/Scripts/angular-animate.js"></script>
19 <script type="text/javascript">
20 (function () {
21 var app = angular.module('cssBasedAnimationTest', ['ngAnimate']);
22 })();
23 </script>
24 </head>
25 <body ng-app="cssBasedAnimationTest">
26 <div ng-if="bool" class="fade">
27 Fade me in out
28 </div>
29 <button ng-click="bool=true">Fade In!</button>
30 <button ng-click="bool=false">Fade Out!</button>
31 </body>
32 </html>
注意:使用CSS Transition時,ng-EVENT(動畫開始前的樣式)和ng-EVENT-active(動畫執行完畢後的樣式)這兩組樣式必須同時出現,且在ng-EVENT中必須包含transition的設置。
本篇開頭提到過,AngularJS核心庫並不包含ngAnimate模塊,因此我們首先需要在定義Module時,添加對ngAnimate模塊引用的聲明:
var app = angular.module('cssBasedAnimationTest', ['ngAnimate']);
使用ngIf(ng-if)來控制class="fade"的元素是否加載到DOM:
<div ng-if="bool" class="fade">
注意:ngIf和ngShow/ngHide不同,ngIf在元素隱藏時DOM中並沒有該元素,而使用ngShow/ngHide時元素依然存在於DOM中。
點擊"Fade In!"按鈕時,加載div到DOM並觸發enter,AngularJS對元素自動添加ng-enter和ng-enter-active的樣式,並從ng-enter到ng-enter-active執行樣式轉換。為了能看清過程,我們將ng-enter中的過渡時間設置為5s,點擊"Fade In!"按鈕後觀察Html的變化。
Step 1(點擊前,如前面所說,ngIf在觸發前,DOM中並沒有div):
Step 2(點擊按鈕後,AngularJS自動添加了ng-animate、ng-enter、ng-enter-active這三個動畫相關的樣式名,並由ngAnimate模塊執行動畫效果):
Step 3(動畫執行完後,示例中是5s後,ng-animate、ng-enter、ng-enter-active被移除,div的狀態為ng-enter-active中指定的狀態):
另外一種CSS transition的方法是使用CSS的Keyframe關鍵字,對於示例1中樣式文件可改為如下:
1 <style type="text/css">
2 /* 開始時的樣式,使用keyframes不需要定義結束時的樣式 */
3 .fade.ng-enter {
4 animation: my_fade_animation 0.5s linear;
5 -webkit-animation: my_fade_animation 0.5s linear;
6 }
7
8 @keyframes my_fade_animation {
9 from {
10 opacity: 0;
11 }
12
13 to {
14 opacity: 1;
15 }
16 }
17
18 @-webkit-keyframes my_fade_animation {
19 from {
20 opacity: 0;
21 }
22
23 to {
24 opacity: 1;
25 }
26 }
27 </style>
這種寫法中是不需要ng-EVENT-active的。
Class-based Animation即為通過ngClass、ngShow、ngHide等Directives執行動畫效果。
示例2:
<!DOCTYPE>
<html>
<head>
<style type="text/css">
.fade.ng-hide {
transition: 3s linear all;
opacity: 0;
}
.fade.ng-show {
transition: 3s linear all;
opacity: 1;
}
</style>
<script src="/Scripts/angular.js"></script>
<script src="/Scripts/angular-animate.js"></script>
<script type="text/javascript">
(function () {
var app = angular.module('cssClassBasedAnimationTest', ['ngAnimate']);
})();
</script>
</head>
<body ng-app="cssClassBasedAnimationTest" ng-init="bool=true">
<div ng-show="bool" class="fade">
This is ng-show.
</div>
<div ng-hide="bool" class="fade">
This is ng-hide.
</div>
<button ng-click="bool=!bool">Toggle</button>
</body>
</html>
本例改自官方Demo,除了官方Demo中有點問題之外,另外我自己添加了.fade.ng-show以及兩個div分別使用ng-show和ng-hide兩個屬性。為了能看清Html的變化,動畫過渡時間也設置成了3s。
圖1:
圖2:
實際觀察Html的變化,無論是ngShow還是ngHide,其實都是在隱藏元素時,默認添加ng-hide-animate、ng-hide-add、ng-hide-add-active樣式。也就是針對像ngHide、ngShow等這些可以感知動畫的Directives,由AngularJS的ngAnimate模塊自動添加了CSS Transition動畫。
ngAminate能檢測的行為是樣式的add或者remove, 那如何顯式的指定add和remove的樣式呢?
示例3(官方Demo):
1 <!DOCTYPE>
2 <html>
3 <head>
4 <style type="text/css">
5 .highlight {
6 transition: 3s linear all;
7 }
8
9 .highlight.on-add {
10 background: white;
11 }
12
13 .highlight.on {
14 background: yellow;
15 }
16
17 .highlight.on-remove {
18 background: black;
19 }
20 </style>
21
22 <script src="/Scripts/angular.js"></script>
23 <script src="/Scripts/angular-animate.js"></script>
24 <script type="text/javascript">
25 (function () {
26 var app = angular.module('cssClassBasedAnimationTest', ['ngAnimate']);
27 })();
28 </script>
29 </head>
30 <body ng-app="cssClassBasedAnimationTest" ng-init="bool=true">
31 <div ng-class="{on:onOff}" class="highlight">
32 Highlight this box
33 </div>
34 <button ng-click="onOff=!onOff">Toggle</button>
35 </body>
36 </html>
我們讓ng-class隨著點擊Toggle按鈕變化,當onOff=true時樣式on會被ngAnimate執行on-add的過程,反之則執行on-remove的過程。由於顯式指定了樣式,當我們運行示例3時,這個過程就一目了然了。
使用基於Javascript的動畫效果可以讓你在腳本中使用其他的Service甚至引用第三方的腳本進行動畫的制作,使動畫效果更豐富多變。
與基於CSS的動畫效果相似,基於Javascript的動畫效果也會由AngularJS自動添加一些指定的樣式到元素上,但基於Javascript的動畫效果還需要使用module.animation()添加動畫腳本。
示例4:
1 <!DOCTYPE>
2 <html>
3 <head>
4 <script src="/Scripts/angular.js"></script>
5 <script src="/Scripts/angular-animate.js"></script>
6 <script src="/Scripts/jquery-1.9.1.js"></script>
7 <script type="text/javascript">
8 (function () {
9 var app = angular.module('javascriptBasedAnimationTest', ['ngAnimate']);
10
11 app.animation('.slide', [function () {
12 return {
13 enter: function (element, doneFn) {
14 jQuery(element).fadeIn(1000, doneFn);
15 },
16
17 move: function (element, doneFn) {
18 jQuery(element).fadeIn(1000, doneFn);
19 },
20
21 leave: function (element, doneFn) {
22 jQuery(element).fadeOut(1000, doneFn);
23 }
24 }
25 }]);
26
27 app.controller('myController', ['$scope', function ($scope) {
28 $scope.students = ["Tom","Jack","Alice","May","Thomas"];
29 }]);
30 })();
31 </script>
32 </head>
33 <body ng-app="javascriptBasedAnimationTest" ng-controller="myController">
34 <div ng-if="isshow" ng-repeat="stu in students" class="slide">
35 {{ stu }}
36 </div>
37 <input type="button" value="Toggle" ng-click="isshow=!isshow" />
38 </body>
39 </html>
注:本例為了便於實現js的動畫效果引入了jQuery。
示例4中,我們對class='slide'的元素的AngularJS中的默認行為添加了動畫行為,當使用ngIf讓元素enter或者remove時,將觸發動畫效果。
關於更復雜的對象,也可參考參考資料中提到的AngularJS Hub的例子,本文就不展開了。
AngularJS官方文檔:https://docs.angularjs.org/api/ngAnimate
ngAnimate:http://www.nganimate.org/
AngularJS Hub: http://www.angularjshub.com/examples/animations/javascriptanimations/