简介

Angular为一些常用的指令(ngRepeat,ngSwitch,ngView)提供了动画的hooks,自动的指令也可以通过$animate服务来实现。这些指令上的动画hook被设置来代替一些繁琐的代码,比如通过条件触发来达到各种效果,比如css的过渡,css形式的动画或者一个js的回调。

一定要在app中注入ngAnimate模块,动画才能起作用。下面是一个可以用于ngShow和ngHide的例子。

<!DOCTYPE html>
<html lang="en" ng-app="myanimate">
<head>
    <Meta charset="UTF-8">
    <title>Title</title>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="bower_components/angular-animate/angular-animate.min.js"></script>
    <style> .content-area { border: 1px solid black; margin-top: 10px; padding: 10px; } .sample-show-hide { transition: all linear 0.5s; } .sample-show-hide.ng-hide { opacity: 0; } </style>
</head>
<body ng-controller="ainmationController">
<div ng-init="checked = true">
    <label>
        <input type="checkBox" ng-model="checked"/>
        Is visible
    </label>
    <div class="content-area sample-show-hide" ng-show="checked">
        Content...
    </div>
</div>
</body>
<script> var myanimation = angular.module("myanimate",['ngAnimate']); myanimation.controller("ainmationController",function () { }); </script>
</html>

工作原理

angularjs的动画是完全基于css的,只要你将相应的css应用到html元素中,你就可以使用动画。下面,我们来看一个repeater的例子。

<!DOCTYPE html>
<html lang="en" ng-app="myanimate">
<head>
    <Meta charset="UTF-8">
    <title>Title</title>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="bower_components/angular-animate/angular-animate.min.js"></script>
    <style> /* 为元素的新增和顺序改变用css的transition方式增加动画效果 */ .repeated-item.ng-enter,.repeated-item.ng-move { transition: all 0.5s linear; opacity: 0; } /* 上面transition方式动画的目标效果 */ .repeated-item.ng-enter.ng-enter-active,.repeated-item.ng-move.ng-move-active { opacity: 1; } /* 为元素的移除使用css3的keyframe方式增加动画效果 */ .repeated-item.ng-leave { animation: 0.5s my_animation; } @keyframes my_animation { from { opacity: 1; } to { opacity: 0; } } </style>
</head>
<body ng-controller="ainmationController as ctrl">
<div ng-repeat="item in items" class="repeated-item">
    {{ item.id }}
</div>
<button ng-click="ctrl.add()">add</button>
<button ng-click="ctrl.remove()">remove</button>
<button ng-click="ctrl.reverse()">reverse</button>

</body>
<script> var myanimation = angular.module("myanimate",['$scope',function ($scope) { $scope.items = []; $scope.items.push({"id": "1001"}); $scope.items.push({"id": "1002"}); $scope.items.push({"id": "1003"}); this.add = function () { $scope.items.push({"id": "1004"}); } this.remove = function () { $scope.items.pop(); } this.reverse = function () { $scope.items.reverse(); } }]); </script>
</html>

每个ng-repeat重复的元素节点都会带有repeated-item的样式,它将告诉每个元素如何演示动画效果。在这里要说明一下:每增加一个元素,这个元素就增加一个ng-enter的css;如果元素顺序发生改变,就会增加一个ng-remove的css;移除一个元素,就会增加一个ng-leave的CSS。这些css会在动画完成后消失。

为了更好的理解,来看一下用jquey实现同样的效果:

myModule.animation('.repeated-item',function() {
  return {
    enter: function(element,done) {
      // 初始化元素的opacity
      element.css('opacity',0);

      // 用opacity方式实现动画
      element.animate({opacity: 1},done);

      // 当取消事件产生后,停止动画
      return function(isCancelled) {
        if (isCancelled) {
          element.stop();
        }
      };
    },leave: function(element,done) {
      element.css('opacity',1);
      element.animate({opacity: 0},done);
      return function(isCancelled) {
        if (isCancelled) {
          element.stop();
        }
      };
    },// 其他事件的动画也是一样的实现方式
    move: function(element,done) {},addClass: function(element,className,removeClass: function(element,done) {}
  }
});

元素上的css决定了angularjs什么时候执行动画,同一个css上如果想css动画和javascript动画一起使用的话需要使用$animateCss.

Class和ngClass的动画hook

angularjs也为css的class更改附加了动画hook,也就是说当css的class的值添加或者移除时就会相应的产生动画效果,但要注意的一点是仅仅ng-class的相应的插值发生改变时才会触发这个动画。

<!DOCTYPE html>
<html lang="en" ng-app="myanimate">
<head>
    <Meta charset="UTF-8">
    <title>Title</title>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="bower_components/angular-animate/angular-animate.min.js"></script>
    <style> .css-class-add,.css-class-remove { transition: all 0.5s cubic-bezier(0.250,0.460,0.450,0.940); } .css-class { color: red; font-size: 3em; } </style>
</head>
<body ng-controller="ainmationController as ctrl">
<p>
    <button ng-click="myCssVar='css-class'">Set</button>
    <button ng-click="myCssVar=''">Clear</button>
    <br>
    <span ng-class="myCssVar">css-Animated Text</span>
</p>
</body>
<script> var myanimation = angular.module("myanimate",function ($scope) { }]); </script>
</html>

支持动画的指令

一些常用的指令在他们生命周期的几个主要事件上可以触发动画,下面列表详细的给出了各个指令可以支持的动画:

指令 动画
ngRepeat enter,leave,and move
ngIf enter and leave
ngSwitch enter and leave
ngInclude enter and leave
ngView enter and leave
ngMessage / ngMessageExp enter and leave
ngClass / {{class}​} add and remove
ngClassEven / ngClassOdd add and remove
ngHide add and remove (the ng-hide class)
ngShow add and remove (the ng-hide class)
ngModel add and remove (varIoUs classes)
form / ngForm add and remove (varIoUs classes)
ngMessages add and remove (the ng-active/ng-inactive classes)

自定义指令中使用动画

自定义的指令可以通过注入$animate间接地使用动画。

myModule.directive('my-directive',['$animate',function($animate) {
  return function(scope,element) {
    element.on('click',function() {
      if (element.hasClass('clicked')) {
        $animate.removeClass(element,'clicked');
      } else {
        $animate.addClass(element,'clicked');
      }
    });
  };
}]);

app引导启动和页面加载时的动画

你可能注意到了,我们之前ng-repeat的例子中,前三个数据是一下就出现的并没有动画,这是因为默认的app启动时的动画是禁止的,这是为了防止在页面有大量的动画时,可能会引起视觉上的混乱,对加载速度也有一定的影响。

在angularjs的内部,ngAnimate要等待app启动的引导完成,再等待模板的下载,还要等当前$digest的完成。一定要确保整个app编译之前,动画是不会运行的。

如果你一定要在app引导启动时产生动画效果,那么你需要在module的run方法中激活anmitate即可,但要注意这个激活是全局的。

myModule.run(function($animate) {
  $animate.enabled(true);
});

怎么样选择性的启动,禁用或者跳过动画

有多种不同的方法来全局禁用动画或者禁用特定的动画。禁用特定的动画可以提升渲染的性能,比如一些很大的ngRepeat列表实际上是没有动画的。即使元素没有一个动画,ngAnimate都在运行时会去检查有没有动画要演示,这是会影响性能的。

在config中,使用$animateProvider.classNameFilter()

这个函数可以在app的配置阶段被调用,它仅仅接受一个正则表达式参数,用于匹配需要展示动画的元素class的名称。正则表达式有极大的灵活性,通过这个可以很方便的指定或者排除相应的动画。

myanimation.config(function ($animateProvider) {
        $animateProvider.classNameFilter(/animate-/);
    })

classNameFilter方法相较于其他策略来讲极大的提高了app的速率,因为匹配是在其他禁用启用策略之前就发生的,但是有个缺点就是无法使用两个classNameFilter策略,只能通过修改class名称的方式来达到动画的启用和禁用。

在run中,使用$animate.enabled()

这个函数启用/禁用动画的方式有两种:

只传一个boolean参数,将会全局的启用/禁用动画,$animate.enabled(false)将会禁用app的所有动画。

当第一个参数是一个原生dom元素或者是jqLite/jQuery的元素时,这个函数可以启用/禁用该元素及其所有子节点的动画:$animate.enabled(myElement,false)。当然你也可用在子节点上重新定义动画的启用/禁用。和classNameFilter不同的是,这个函数实在app的运行阶段作用的。

<body ng-controller="ainmationController as ctrl">
<p>
    <button ng-click="myCssVar='css-class'">Set</button>
    <button ng-click="myCssVar=''">Clear</button>
    <br>
    <span ng-class="myCssVar">css-Animated Text</span>
</p>
</body>
<script> var myanimation = angular.module("myanimate",['ngAnimate']); myanimation.run(function ($animate) { $animate.enabled(true); $animate.enabled(angular.element(document).find('p'),false); $animate.enabled(angular.element(document).find('span'),true); }).controller("ainmationController",function ($scope) { }]); </script>

有一点需要再重申一次:$animateProvider.classNameFilter()
策略的优先级要高于$animate.enabled()

通过css class:用ng-animate重写css class

当动画启动后,ngAnimate会在附加ng-animate的class在对应的元素上,持续整个动画周期,通过附加transition/animation的样式,可以成功跳过该动画。

修改一下我们之前的例子,附加上这两段,动画就不会再出现了:

.css-class-add.ng-animate { transition: 0s; }

.css-class-remove.ng-animate{ transition: 0s; }

通过把transition设为0s,可以让ngAnimate忽略掉已经存在的动画的样式,当然javascript的动画仍会执行。

在动画开始前防止闪烁

当在一个结构和的嵌套元素的动画中,比如ngIf动画嵌套在一个基于ngClass的DOM结构中时,在动画的启动过程中,有时会有一个短暂的闪烁产生。

为了不至于这样,你可以增加ng-[event]-prepare的class,这个class会在动画初始化的时候附加在元素上,当动画开始之前就会消失掉。这个class只在结构性的动画时产生(enter,move,and leave)。

以下是个防止闪烁的例子,你可以去掉注释标明的地方试下。

<!DOCTYPE html>
<html lang="en" ng-app="myanimate">
<head>
    <Meta charset="UTF-8">
    <title>Title</title>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="bower_components/angular-animate/angular-animate.min.js"></script>
    <style> .red { background: red; border: 1px solid black; padding: 10px; } .blue { background: blue; border: 1px solid black; padding: 10px; } .message { background: white; border: 1px solid black; padding: 10px; } .message.ng-enter,.message.ng-leave { transition: all cubic-bezier(0.250,0.940) 1s; } .message.ng-enter,.message.ng-enter-prepare,/*不加这行就会闪烁*/ .message.ng-leave.ng-leave-active { opacity: 0; } .message.ng-leave,.message.ng-enter.ng-enter-active { opacity: 1; } </style>
</head>
<body ng-controller="ainmationController as ctrl">
<div ng-class="{red: myProp}">
    <div ng-class="{blue: myProp}">
        <div class="message" ng-if="myProp">message</div>
    </div>
</div>
</body>
<script> var myanimation = angular.module("myanimate",['ngAnimate']); myanimation.run(function ($animate) { $animate.enabled(true); }).controller("ainmationController",function ($scope) { $scope.myProp = true; }]); </script>
</html>

angular学习十七——-Animations的更多相关文章

  1. Canvas实现贝赛尔曲线轨迹动画的示例代码

    这篇文章主要介绍了Canvas实现贝赛尔曲线轨迹动画的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. css绝对定位如何在不同分辨率下的电脑正常显示定位位置?(一定要看!)

    这篇文章主要介绍了css绝对定位如何在不同分辨率下的电脑正常显示定位位置,本文首先解释了常见的电脑分辨率,为了页面在不同的分辨率下正常显示,要给页面一个安全宽度,再去使用绝对定位,具体操作步骤大家可查看下文的详细讲解,感兴趣的小伙伴们可以参考一下。

  3. 详解HTML5中CSS外观属性

    这篇文章主要介绍了HTML5中CSS外观属性的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,,需要的朋友可以参考下

  4. HTML5 直播疯狂点赞动画实现代码 附源码

    为了烘托直播间的氛围,直播相对于普通视频或者文本内容,点赞动作通常无限次,引导用户疯狂点赞,今天小编给大家分享HTML5 直播疯狂点赞动画实现代码 附源码,感兴趣的朋友一起看看吧

  5. CSS中实现动画效果-附案例

    这篇文章主要介绍了 CSS中实现动画效果并附上案例代码及实现效果,就是CSS动画样式处理,动画声明需要使用@keyframes name,后面的name是人为定义的动画名称,下面我们来看看文章的具体实现内容吧,需要的小伙伴可以参考一下

  6. 基于canvas的骨骼动画的示例代码

    这篇文章主要介绍了基于canvas的骨骼动画的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. html5如何在Canvas中实现自定义路径动画示例

    本篇文章主要介绍了html5如何在Canvas中实现自定义路径动画示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. 基于HTML5+Webkit实现树叶飘落动画

    本文给大家分享一段实例代码给大家介绍基于HTML5+Webkit实现树叶飘落动画效果,需要的朋友参考下吧

  10. Html5页面内使用JSON动画的实现

    这篇文章主要介绍了Html5页面内使用JSON动画的实现的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部