单页应用(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)