最近在看算法分析,那個大O啊,小o啊,分治法啊(目前就看到這里),真是搞死了。這回呢休息一下,學學AngularJS動畫,上一篇文章根據自由男人的書簡單談到了動畫的話題,發現反響很大(好吧,我說慌了,那篇文章的動畫談得太簡單了),今天來看看官方文檔。嗯,邊看邊寫。
一、安裝
這個應該都知道了,和其他的擴展模塊安裝相同。這里為了文章完整性簡單提一下。文檔給到了獲取動畫擴展angular-animate.js
的多種方式。
1、cdn,自己去查
2、npm install --save angular-animate@X.Y.Z
3、bower install angular-animate#X.Y.Z
拿到這個文件后需要引入到我們要應用動畫的頁面,添加依賴ngAnimate。
二、使用
動畫的使用方式有兩種,一是CSS,二是通過javascript。前者是通過純粹的css來實現動畫,后者通過腳本觸發動畫。兩者都需要用到Angrular提供的一些特殊的類。
1、支持動畫的指令
最后兩個指令屬於一個擴展模塊ngMessages
,為了集中火力搞動畫,先不管。
2、基於CSS的動畫
CSS動畫的特殊性在於你不需要寫一行javascript就可以創建出炫酷的動畫,這讓我想到了Bootstrap,她只要在html元素上添加一些特定的屬性就可以實現一些動畫。Angularjs基於CSS實現動畫的原理很簡單,即,如果你為某個指令加上了一些類比如fade,而你在樣式表中這樣寫.fade.ng-leave
,這樣如果元素沒有ng-leave這個類,你加的fade的樣式就不會被運用,但是Angularjs會監視我們的指令,當檢測到指令進入某種狀態時就會添加相應的類,從而你的樣式就會被使用了,如此,動畫就觸發了。下面給個例子
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>animate</title> <style type="text/css"> #div{ width: 300px; height: 300px; background:red; } .ani.ng-hide{ transition: 6s linear all; opacity: 0; background: blue; } </style> </head> <body> <div ng-controller='animateCtrl'> <div id="div" class="ani" ng-show='show'></div> <button ng-click='clickHandler()'>change</button> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript" src="../node_modules/angular-animate/angular-animate.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",['ngAnimate']); myApp.controller("animateCtrl",function($scope){ $scope.show = true; $scope.clickHandler = function(){ $scope.show = !$scope.show; } }) </script> </body> </html>
我們看一下當單擊按鈕隱藏時發生了什么。
看到沒,angular給我們動態添加了很多類,正是因為如此,我們的動畫樣式才能被應用。
有開始有結束
/* The starting CSS styles for the enter animation */
.fade.ng-enter {
transition:0.5s linear all;
opacity:0;
}
/* The finishing CSS styles for the enter animation */
.fade.ng-enter.ng-enter-active {
opacity:1;
}
angularjs對動畫元素的狀態進行了管理,可以標識狀態的開始如ng-enter 和狀態的結束 ng-enter-active.我們可以在狀態開始指定動畫的初始狀態,狀態的結束指定動畫的最終狀態。
另外,angular提供了自己加類的機制。
<div ng-class="{on:onOff}" class="highlight"> Highlight this box </div> <button ng-click="onOff=!onOff">Toggle</button> <style> .highlight { transition:0.5s linear all; } .highlight.on-add { background:white; } .highlight.on { background:yellow; } .highlight.on-remove { background:black; } </style>
這個例子的意思是,如果onOff為真,那么給元素加上on這個類,在添加的過程中會添加on-add類,當onOff為false是,會為元素添加一個on-remove,當然,這個on-remove只存在與由true變為false的過程。
有時候我們希望進入某個狀態后並不立即執行動畫,而是延遲執行,你一定想到了transition-delay或者animation-delay,ng也給我們提供了實現的方法。
.my-animation.ng-enter-stagger {
/* this will have a 100ms delay between each successive leave animation */
transition-delay: 0.1s;
/* As of 1.4.4, this must always be set: it signals ngAnimate
to not accidentally inherit a delay property from another CSS class */
transition-duration: 0s;
/* if you are using animations instead of transitions you should configure as follows:
animation-delay: 0.1s;
animation-duration: 0s; */
}
就像這個樣子,給我們的動畫類加上一個叫.ng-xx-stagger的東東。
介紹一個狀態,在動畫開始之前的狀態,ng-xx-prepare,xx 可以是
enter
, move
, and leave
。用法如下:
.message.ng-enter-prepare {
opacity: 0;
}
這個可以給我們的元素在沒有開始動畫(或者叫即將開始吧)的情況下設置樣式。
3、基於javascript的動畫
ngAmination模塊允許使用javascript使用其動畫功能,方式與CSS類似,不同的是它需要調一個模塊的animation() 方法,使用js的好處是我們可以用一些優秀的js動畫庫來設計動畫。
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>animate3</title> <style type="text/css"> #hh{ width: 100px; height: 50px; background: red; } </style> </head> <body> <div ng-controller='animateCtrl'> <div id="hh" ng-if="bool" class="slide"> 大家好! </div> <button ng-click="handler()">點我</button> </div> <script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript" src="../node_modules/angular-animate/angular-animate.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",['ngAnimate']); myApp.controller("animateCtrl",function($scope){ $scope.handler = function(){ $scope.bool = !$scope.bool; } }); myApp.animation('.slide', [function() { return { // make note that other events (like addClass/removeClass) // have different function input parameters enter: function(element, doneFn) { jQuery(element).fadeIn(1000, doneFn); // remember to call doneFn so that AngularJS // knows that the animation has concluded }, leave: function(element, doneFn) { jQuery(element).fadeOut(10000, doneFn); } } }]); </script> </body> </html>
不同指令支持的動畫有區別,可以參見本文最前面的圖,本例中用到了enter,和leave。
4、基於css的方式和基於javascript的方式可以混用嗎
文檔講:如果css方式和js方式使用了相同的css類,那么css方式將不能工作。但是,我們可以通過js去讓我們用css方式定義的動畫執行,這就需要一個新的服務叫做$animateCss。
myModule.animation('.slide', ['$animateCss', function($animateCss) {
return {
enter: function(element) {
// this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
return $animateCss(element, {
event: 'enter',
structural: true
});
}
}
}]);
下文中對$animateCss進行詳細介紹,這里簡單提示。
5、錨動畫
<!-- index.html --> <div ng-view class="view-animation"> </div> <!-- home.html --> <a href="#/banner-page"> <img src="./banner.jpg" class="banner" ng-animate-ref="banner"> </a> <!-- banner-page.html --> <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
.banner.ng-anchor {
/* this animation will last for 1 second since there are
two phases to the animation (an `in` and an `out` phase) */
transition:0.5s linear all;
}
.view-animation.ng-enter, .view-animation.ng-leave {
transition:0.5s linear all;
position:fixed;
left:0;
top:0;
width:100%;
}
.view-animation.ng-enter {
transform:translateX(100%);
}
.view-animation.ng-leave,
.view-animation.ng-enter.ng-enter-active {
transform:translateX(0%);
}
.view-animation.ng-leave.ng-leave-active {
transform:translateX(-100%);
}
這里貼出文檔的例子,ng-animate-ref的意思是將表明組件的關系,這樣在寫動畫是就可以只用一個類是兩個組件效果相同,.ng-anchor-in .ng-anchor-out .ng-anchor分別是在某組件顯示,某組件卸載,顯示卸載時添加的類,這樣可以在不同的狀態運用動畫。你可以看看文檔的一個DEMO:https://plnkr.co/edit/?p=preview
關於angular是如何實現變形的,如何實現移動的感興趣可以看看https://docs.angularjs.org/api/ngAnimate
三、$animate服務
$animate服務提供了一些實現動畫的工具方法,官方建議是只應該將其用在與dom相關的動畫指令中。這翻譯的自己都不明白了,英語太差了,如果你想了解更多自己去官網看看,別看我瞎扯了。
1、on(event, container, callback)
這個方法的目的是設置事件偵聽器,一旦某元素上觸發動畫事件(前文有提到的enter,leave等),其中的回調函數將被調用。
這個方法接受三個參數:event表示要偵聽的動畫事件類型,container是一個dom元素,表示要偵聽的dom元素(注意他是有事件代理功能的,及子元素的事件會冒泡到該元素被捕獲),callback是個回調函數,當事件被觸發是執行,可以有兩個參數,第一個表示觸發事件的元素,第二個表示動畫階段個:值start表動畫開始,值close表動畫結束。
2、off(event, [container], [callback])
這個方法是移出元素的偵聽器,參數與上一個方法的類似。
3、pin(element, parentElement)
不太能夠理解這個方法。文檔說這個方法能夠讓angular應用之外的元素能夠執行動畫,一般來將我們的angular應用的dom元素都是包含在ng-app內的,也就是說沒有元素跑到angular應用之外,所以這個方法很讓我費解。
4、enabled([element], [enabled])
此方法用於啟用或禁用動畫。有四種使用方法。
// returns true or false
$animate.enabled();
// changes the enabled state for all animations
$animate.enabled(false);
$animate.enabled(true);
// returns true or false if animations are enabled for an element
$animate.enabled(element);
// changes the enabled state for an element and its children
$animate.enabled(element, true);
$animate.enabled(element, false);
5、cancel(animationPromise)
用於取消動畫執行。
6、enter(element, parent, [after], [options])
將element作為parent的第一個子元素或者after元素后面的元素。options是一個對象可有下面這幾個屬性:
- addClass -
添加到element的類
- from -
{Object}
-表示動畫開始時的css樣式
- removeClass -
{string}
-移除element類 - to -
{Object}
-表示動畫結束時的css樣式
這個方法返回一個promise對象,動畫完成時變為resolved狀態。
7、move(element, parent, [after], [options])
將element移動到一個新的位置。返回一個promise,與enter()類似。
8、leave(element, [options])
觸發動畫然后刪除element
9、addClass(element, className, [options])
將className類加到element上並觸發addClass事件。
10、removeClass(element, className, [options])
移出className類並觸發removeClass事件。
11、setClass(element, add, remove, [options])
12、animate(element, from, to, [className], [options])
本文給到了一個angular動畫的一個參考,涉及到ngAnimate的一些個用法,包括如何用CSS指定動畫,如何用js觸發動畫等,然后講到了$animate服務,不過感覺官網講的也不夠詳細(也可能是我的英語太差了)。與angular動畫相關的還有$aniamteCss服務,本文沒有講,防止越講越亂,感覺上面講的已經夠亂了。
參考: