單頁應用(Single Page Web Application)每每有一個基本的要點,那就是把多個視圖集成到一個網頁內,而後去控制這些視圖的顯示和隱藏。此外,視圖的切換動做幾乎都會引入動畫效果,以得到更平滑、流暢的瀏覽體驗。javascript
若是想要很快速地製做出包含視圖動畫的單頁應用?css
Angular會是一個不錯的選擇。下面,本文將說明如何用Angular(v1.4.3)來完成製做。你也許會以爲這個過程至關簡單。html
視圖切換,其實就是切換DOM顯示。Angular有一個ngSwtich,從名字就能夠看出,正是拿來作「切換」工做的。java
參考Angular的ngSwitch用法,能夠想到這樣的html:git
<body ng-app="morin" ng-strict-di> <div class="view-container" ng-controller="viewController as view" ng-switch="view.current"> <div class="view-page view-1" ng-switch-when="1"></div> <div class="view-page view-2" ng-switch-when="2"></div> </div> <!-- scripts --> </body>
在這段代碼中,div.view-page
分別表明不一樣的視圖,它們都被包含在div.view-container
這樣一個視圖容器中。視圖容器元素上建立了名爲viewController
的Controller,並定義了關聯名view
(或者叫簡稱)。angularjs
視圖容器上的ng-switch
,指定了一個變量view.current
,用來判斷當前顯示哪一個視圖。對應的,在已有的兩個視圖內,分別用ng-swtich-when
指定了1
和2
這樣的值。想想JavaScript的switch語句,這個結構會是怎樣的效果,就很好理解了。github
這些視圖對應的css是:api
.view-page{ position: absolute; width: 100%; height: 100%; left: 0; top: 0; } .view-1{ background: #b3c589; } .view-2{ background: #8fc241; }
這裏的background
是給每一個視圖帶上背景,用做標識。瀏覽器
ngAnimate是Angular的一個附屬module,能夠爲Angular應用增長動畫支持。在加入ngAnimate後,ngSwitch的切換過程所涉及的兩個元素,會分別被Angular添加不一樣的class。其中,ng-enter
表明進場,ng-enter-active
表明進場動畫終點,ng-leave
表明退場,ng-leave-active
表明退場動畫終點。只須要藉助這些class,咱們就能夠用css建立切換過程的動畫(瀏覽器私有前綴已省略):mvc
.view-page.ng-enter{ transition: transform .5s; transform: translateX(100%); } .view-page.ng-enter.ng-enter-active{ transform: translateX(0); } .view-page.ng-leave{ transition: transform .5s; } .view-page.ng-leave.ng-leave-active{ transform: translateX(-100%); }
這段代碼是一個使用transition
製做了簡單的平移動畫的例子。其中每一段定義都有的.view-page
,是爲了限定只有視圖元素纔得到這個動畫效果。
transition
動畫的要點是,transition
屬性自己必須定義在ng-enter
或ng-leave
這樣表示動畫起點的class上。而後,動畫終點class上再定義終點樣式。
若是使用animation
的css動畫,則只須要用到動畫起點的class:
.view-page.ng-enter{ animation: moveFromRight .5s both; } .view-page.ng-leave{ animation: moveToLeft .5s both; } @keyframes moveFromRight{ from { transform: translateX(100%); } } @keyframes moveToLeft{ to { transform: translateX(-100%); } }
這段使用animation
的代碼將能夠得到和前面相同的動畫效果。
若是想要視圖1和視圖2各自有不一樣的進場和退場動畫,用class去限定便可:
.view-1.ng-enter{ } .view-2.ng-enter{ } /* ... */
有關更多的視圖切換動畫,推薦參考A Collection of Page Transitions。
下面加入JavaScript完成功能。代碼是(外層包裝函數已省略):
angular .module("morin", ["ngAnimate"]) .controller("viewController", viewController); function viewController(){ var view = this; view.current = "1"; // Here, change "view.current" to switch views with animation. }
沒錯,只須要這樣一小段。而後,在viewController
函數的代碼範圍內,只要更改view.current
這一個變量的值,就能夠完成帶動畫效果的視圖切換。
很方便?如今,視圖1內有一個按鈕元素,咱們但願它點擊後切換到視圖2,那麼這樣作就搞定了:
<a class="m-btn" href="javascript:" ng-click="view.current='2'"></a>
若是除了切換,還要作點別的,通常這樣作:
<a class="m-btn" href="javascript:" ng-click="view.doSomething()"></a>
對應JavaScript:
function viewController(){ // ... (the same as before) view.doSomething = doSomething; function doSomething(){ // Do what you want. view.current = "2"; } }
至此,帶有視圖切換動畫的單頁應用就完成了。完成後的效果可能像這樣(點擊切換,限支持的瀏覽器):
http://runjs.cn/detail/ntrenbml
它包括4個視圖,每一個視圖都定義了不一樣的進場和退場動畫。
使用ngSwitch須要注意的是,最初在html內用ng-switch-when
指定的值,只會被當作字符串進行識別。因此你也能夠看到前文中的代碼使用的是字符串的"1"
。
ngSwtich切換DOM顯示並不經過css的display
屬性實現,而是真正從DOM中添加和移除元素。所以,若是視圖元素中有子Controller,使用$scope.$emit()
能夠發佈事件到上層,如viewController的$scope
,但反過來,viewController使用$scope.$broadcast()
向下發佈事件,則可能會由於DOM當前不存在而接收不到。
JavaScript代碼通常都會放在比較靠後的位置執行,在代碼未運行完畢以前,可能會出現先看到未經JavaScript處理的html的狀況(並帶來一種閃爍的感受)。好比本文例子中,ngSwitch中的多個視圖初始都是顯示的,只是在JavaScript代碼運行後才隱藏非當前視圖。
Angular提供了ngCloak
來解決這個問題。在本文例子中,能夠在div.view-container
上添加自定義屬性ng-cloak
,並在頁面css內補充這樣的樣式:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }
也就是說,先隱藏,而後Angular會在加載完成後再移除ngCloak
標記。
考慮Angular(v1.4.x)自己以及css動畫的兼容性,須要IE10+及其餘現代瀏覽器。若是是移動端應用,那麼在當前主流手機瀏覽器上都是可用的。
本文假定你已經瞭解了最基本的Angular用法。若是想要從零開始,推薦參考AngularJS for Absolute Beginners和AngularJS TodoMVC Example。
提及來,我也贊同一個觀點是,Angular的學習成本不低。但就本文的例子來看,要製做這樣一個像模像樣的單頁應用,是否是還挺簡單的呢?對Angular有基本的瞭解就能夠了。
固然,本文才不是說由於一個功能點的實現,就應該去引入Angular這樣的框架。請理解爲,若是用Angular開發單頁應用,至少它的視圖切換動畫會很容易作!
(從新編輯自個人博客,原文地址:http://acgtofe.com/posts/2015/08/view-transitions-with-angularjs)