用Angular製做單頁應用視圖切換動畫

視圖,動畫

單頁應用(Single Page Web Application)每每有一個基本的要點,那就是把多個視圖集成到一個網頁內,而後去控制這些視圖的顯示和隱藏。此外,視圖的切換動做幾乎都會引入動畫效果,以得到更平滑、流暢的瀏覽體驗。javascript

若是想要很快速地製做出包含視圖動畫的單頁應用?css

Angular會是一個不錯的選擇。下面,本文將說明如何用Angular(v1.4.3)來完成製做。你也許會以爲這個過程至關簡單。html

切換DOM的ngSwitch

視圖切換,其實就是切換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指定了12這樣的值。想想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

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-enterng-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的斷定值是字符串

使用ngSwitch須要注意的是,最初在html內用ng-switch-when指定的值,只會被當作字符串進行識別。因此你也能夠看到前文中的代碼使用的是字符串的"1"

ngSwitch會移除DOM

ngSwtich切換DOM顯示並不經過css的display屬性實現,而是真正從DOM中添加和移除元素。所以,若是視圖元素中有子Controller,使用$scope.$emit()能夠發佈事件到上層,如viewController的$scope,但反過來,viewController使用$scope.$broadcast()向下發佈事件,則可能會由於DOM當前不存在而接收不到。

保障初始狀態的ngCloak

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...

本文假定你已經瞭解了最基本的Angular用法。若是想要從零開始,推薦參考AngularJS for Absolute BeginnersAngularJS TodoMVC Example

結語

提及來,我也贊同一個觀點是,Angular的學習成本不低。但就本文的例子來看,要製做這樣一個像模像樣的單頁應用,是否是還挺簡單的呢?對Angular有基本的瞭解就能夠了。

固然,本文才不是說由於一個功能點的實現,就應該去引入Angular這樣的框架。請理解爲,若是用Angular開發單頁應用,至少它的視圖切換動畫會很容易作!

(從新編輯自個人博客,原文地址:http://acgtofe.com/posts/2015/08/view-transitions-with-angularjs

相關文章
相關標籤/搜索