一、路由动画

路由动画需要在host元数据中指定触发器。动画注意不要过多,否则适得其反。

内容优先,引导用户去注意到某个内容。动画只是辅助手段。

定义一个进场动画,一个离场动画。

因为进场动画和离场动画用的特别频繁,有一个别名叫:enter:leave

  1. import { trigger, state, transition, style, animate} from '@angular/animations';
  2.  
  3. export const slideToRight = trigger('routeAnim',[
  4. state('void',style({'position':'fixed','width':'100%','height':'100%'})),
  5. state('*',style({'position':'fixed','width':'100%','height':'80%'})),
  6. transition('void => *',[
  7. style({transform:'translateX(-100%)'}),
  8. animate('.5s ease-in-out', style({transform:'translateX(0)'}))
  9. ]),
  10. transition('* => void',[
  11. style({transform:'translateX(0)'}),
  12. animate('.5s ease-in-out', style({transform:'translateX(100%)'}))
  13. ]),
  14. ]);

在project-list中使用路由动画。

  1. import { Component, OnInit , HostBinding } from "@angular/core";
  2. import { MatDialog } from "@angular/material";
  3. import { NewProjectComponent } from "../new-project/new-project.component";
  4. import { InviteComponent } from '../invite/invite.component';
  5. import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
  6. import {slideToRight} from '../../animate/router.animate'
  7.  
  8. @Component({
  9. selector: "app-project-list",
  10. templateUrl: "./project-list.component.html",
  11. styleUrls: ["./project-list.component.scss"],
  12. animations:[
  13. slideToRight
  14. ]
  15. })
  16. export class ProjectListComponent implements OnInit {
  17. @HostBinding('@routeAnim') state;
  18.  
  19. projects = [
  20. {
  21. name: "企业协作平台",
  22. desc: "这是一个企业内部项目",
  23. coverImg: "assets/images/covers/0.jpg"
  24. },
  25. {
  26. name: "自动化测试项目",
  27. desc: "这是一个企业内部项目",
  28. coverImg: "assets/images/covers/2.jpg"
  29. }
  30. ];
  31. constructor(private dialog: MatDialog) { }
  32.  
  33. ngOnInit() { }
  34.  
  35. openNewProjectDialog() {
  36. // this.dialog.open(NewProjectComponent,{data:'this is a dialog'});
  37. const dialogRef = this.dialog.open(NewProjectComponent, {
  38. data: { title: '新建项目' }
  39. });
  40. dialogRef.afterClosed().subscribe((result) => {
  41. console.log(result);
  42. });
  43. }
  44.  
  45. lauchInviteDialog() {
  46. const dialogRef = this.dialog.open(InviteComponent);
  47. }
  48.  
  49. lauchUpdateDialog() {
  50. const dialogRef = this.dialog.open(NewProjectComponent, {
  51. data: { title: '编辑项目' }
  52. });
  53. }
  54.  
  55. lauchConfimDialog() {
  56. const dialogRef = this.dialog.open(ConfirmDialogComponent, {
  57. data: { title: '编辑项目', content: '您确认删除该项目吗?' }
  58. });
  59. }
  60. }

在task-home中使用路由动画。

  1. import { Component, OnInit , HostBinding } from "@angular/core";
  2. import { NewTaskComponent } from "../new-task/new-task.component";
  3. import { MatDialog } from "@angular/material";
  4. import { CopyTaskComponent } from "../copy-task/copy-task.component";
  5. import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component";
  6. import { NewTaskListComponent } from "../new-task-list/new-task-list.component";
  7. import {slideToRight} from '../../animate/router.animate';
  8.  
  9. @Component({
  10. selector: "app-task-home",
  11. templateUrl: "./task-home.component.html",
  12. styleUrls: ["./task-home.component.scss"],
  13. animations:[
  14. slideToRight
  15. ]
  16. })
  17. export class TaskHomeComponent implements OnInit {
  18. constructor(private dialog: MatDialog) {}
  19.  
  20. @HostBinding('@routeAnim') state;
  21. ngOnInit() {}
  22.  
  23. launchNewTaskDialog() {
  24. // this.dialog.open(NewTaskComponent);
  25. const dialogRef = this.dialog.open(NewTaskComponent, {
  26. data: { title: "新建任务" }
  27. });
  28. }
  29. lauchCopyTaskDialog() {
  30. const dialogRef = this.dialog.open(CopyTaskComponent, {
  31. data: { lists: this.lists }
  32. });
  33. }
  34.  
  35. launchUpdateTaskDialog(task) {
  36. const dialogRef = this.dialog.open(NewTaskComponent, {
  37. data: { title: "修改任务", task: task }
  38. });
  39. }
  40.  
  41. launchConfirmDialog() {
  42. const dialogRef = this.dialog.open(ConfirmDialogComponent, {
  43. data: { title: "删除任务列表", content: "您确定要删除该任务列表吗?" }
  44. });
  45. }
  46.  
  47. launchEditListDialog() {
  48. const dialogRef = this.dialog.open(NewTaskListComponent, {
  49. data: { title: "更改列表名称" }
  50. });
  51. dialogRef.afterClosed().subscribe(result => console.log(result));
  52. }
  53. launchNewListDialog() {
  54. const dialogRef = this.dialog.open(NewTaskListComponent, {
  55. data: { title: "新建列表名称" }
  56. });
  57. dialogRef.afterClosed().subscribe(result => console.log(result));
  58. }
  59. lists = [
  60. {
  61. id: ,
  62. name: "待办",
  63. tasks: [
  64. {
  65. id: ,
  66. desc: "任务一: 去星巴克买咖啡",
  67. completed: true,
  68. priority: ,
  69. owner: {
  70. id: ,
  71. name: "张三",
  72. avatar: "avatars:svg-11"
  73. },
  74. dueDate: new Date(),
  75. reminder: new Date()
  76. },
  77. {
  78. id: ,
  79. desc: "任务一: 完成老板布置的PPT作业",
  80. completed: false,
  81. priority: ,
  82. owner: {
  83. id: ,
  84. name: "李四",
  85. avatar: "avatars:svg-12"
  86. },
  87. dueDate: new Date()
  88. }
  89. ]
  90. },
  91. {
  92. id: ,
  93. name: "进行中",
  94. tasks: [
  95. {
  96. id: ,
  97. desc: "任务三: 项目代码评审",
  98. completed: false,
  99. priority: ,
  100. owner: {
  101. id: ,
  102. name: "王五",
  103. avatar: "avatars:svg-13"
  104. },
  105. dueDate: new Date()
  106. },
  107. {
  108. id: ,
  109. desc: "任务一: 制定项目计划",
  110. completed: false,
  111. priority: ,
  112. owner: {
  113. id: ,
  114. name: "李四",
  115. avatar: "avatars:svg-12"
  116. },
  117. dueDate: new Date()
  118. }
  119. ]
  120. }
  121. ];
  122. }

定义路由

  1. <mat-list-item [routerLink]="['/project']">
  2. <mat-icon mat-list-icon svgIcon="projects"></mat-icon>
  3. <h4 mat-line>项目首页</h4>
  4. <p mat-line mat-subheader> 查看您的所有项目</p>
  5. </mat-list-item>
  6. <mat-list-item [routerLink]="['/task']">
  7. <mat-icon mat-list-icon svgIcon="projects"></mat-icon>
  8. <h4 mat-line>任务首页</h4>
  9. <p mat-line mat-subheader> 查看您的所有项目</p>
  10. </mat-list-item> 

注意:一定要用HostBinding形式。

二、Group

用于同时进行一组动画变换

group([animate(...),animate(...)...])接收一个数组,数组里写多个动画。

  1. import { trigger, state, transition, style, animate, group} from '@angular/animations';
  2.  
  3. export const slideToRight = trigger('routeAnim',[
  4. state('void',style({'position':'fixed','width':'100%','height':'80%'})),
  5. state('*',style({'position':'fixed','width':'100%','height':'80%'})),
  6. transition(':enter',[
  7. style({transform:'translateX(-100%)',opacity:''}),
  8. group([
  9. animate('.5s ease-in-out', style({transform:'translateX(0)'})),
  10. animate('.3s ease-in', style({opacity:}))
  11. ])
  12. ]),
  13. transition(':leave',[
  14. style({transform:'translateX(0)',opacity:''}),
  15. group([
  16. animate('.5s ease-in-out', style({transform:'translateX(100%)'})),
  17. animate('.3s ease-in', style({opacity:}))
  18. ])
  19. ]),
  20. ]);

三、Query & Stagger

Query用于父节点寻找子节点,把动画应用到选中元素。非常强大。

Stagger指定有多个满足Query的元素,每个的动画之间有间隔。

做一个示例:新建的时候同时新建2个项目,两个新建出的项目的动画依次产生,第一个完成后才开始第二个。

建立list.animate.ts

进场动画,先隐藏起来,通过stagger间隔1000s做一个1s的动画。

  1. import { trigger, state, transition, style, animate, query, animation,stagger} from '@angular/animations';
  2.  
  3. export const listAnimation = trigger('listAnim', [
  4. transition('* => *', [
  5. query(':enter', style({opacity: }), { optional: true }), //加入optional为true,后面的状态动画都是可选的
  6. query(':enter', stagger(, [
  7. animate('1s', style({opacity: }))
  8. ]), { optional: true }),
  9. query(':leave', style({opacity: }), { optional: true }),
  10. query(':leave', stagger(, [
  11. animate('1s', style({opacity: }))
  12. ]), { optional: true })
  13. ])
  14. ]);

在project_list中使用

应用query动画一般都是跟*ngFor在一起的,需要外面套一层div。

  1. <div class="container" [@listAnim]="projects.length">
  2. <app-project-item *ngFor="let project of projects" [item]="project"
  3. class="card"
  4. (onInvite)="lauchInviteDialog()"
  5. (onEdit)="lauchUpdateDialog()"
  6. (onDelete)="lauchConfimDialog(project)">
  7. </app-project-item>
  8. </div>
  9. <button class="ab-buttonmad-fab fab-button" mat-fab type="button" (click)="openNewProjectDialog()">
  10. <mat-icon>add</mat-icon>
  11. </button>

修改对应的css

  1. // :host{
  2. // display: flex;
  3. // flex-direction: row;
  4. // flex-wrap: wrap;
  5. // }
  6.  
  7. //把host改为div
  8. .container{
  9. display: flex;
  10. flex-direction: row;
  11. flex-wrap: wrap;
  12. }

修改一下component

  1. import { Component, OnInit , HostBinding } from "@angular/core";
  2. import { MatDialog } from "@angular/material";
  3. import { NewProjectComponent } from "../new-project/new-project.component";
  4. import { InviteComponent } from '../invite/invite.component';
  5. import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
  6. import {slideToRight} from '../../animate/router.animate'
  7. import { listAnimation } from '../../animate/list.animate';
  8. import { projection } from '@angular/core/src/render3';
  9.  
  10. @Component({
  11. selector: "app-project-list",
  12. templateUrl: "./project-list.component.html",
  13. styleUrls: ["./project-list.component.scss"],
  14. animations:[
  15. slideToRight,listAnimation //第一步,导入listAnimation
  16. ]
  17. })
  18. export class ProjectListComponent implements OnInit {
  19. @HostBinding('@routeAnim') state;
  20.  
  21. //第二步,改造一下数组,加id
  22. projects = [
  23. {
  24. id:,
  25. name: "企业协作平台",
  26. desc: "这是一个企业内部项目",
  27. coverImg: "assets/images/covers/0.jpg"
  28. },
  29. {
  30. id:,
  31. name: "自动化测试项目",
  32. desc: "这是一个企业内部项目",
  33. coverImg: "assets/images/covers/2.jpg"
  34. }
  35. ];
  36. constructor(private dialog: MatDialog) { }
  37.  
  38. ngOnInit() { }
  39.  
  40. //第三步,新增元素时hard code一下
  41. openNewProjectDialog() {
  42. // this.dialog.open(NewProjectComponent,{data:'this is a dialog'});
  43. const dialogRef = this.dialog.open(NewProjectComponent, {
  44. data: { title: '新建项目' }
  45. });
  46. dialogRef.afterClosed().subscribe((result) => {
  47. console.log(result);
  48. this.projects = [...this.projects,
  49. {id:,name:'一个新项目',desc:'这是一个新项目',coverImg:"assets/images/covers/3.jpg"},
  50. {id:,name:'又一个新项目',desc:'这是又一个新项目',coverImg:"assets/images/covers/4.jpg"}]
  51. });
  52. }
  53.  
  54. lauchInviteDialog() {
  55. const dialogRef = this.dialog.open(InviteComponent);
  56. }
  57.  
  58. lauchUpdateDialog() {
  59. const dialogRef = this.dialog.open(NewProjectComponent, {
  60. data: { title: '编辑项目' }
  61. });
  62. }
  63.  
  64. //第四步,改造一下删除项目
  65. lauchConfimDialog(project) {
  66. const dialogRef = this.dialog.open(ConfirmDialogComponent, {
  67. data: { title: '删除项目', content: '您确认删除该项目吗?' }
  68. });
  69. dialogRef.afterClosed().subscribe(result=>{
  70. console.log(result);
  71. this.projects=this.projects.filter(p=>p.id!=project.id);
  72. });
  73. }
  74. }

Stagger使得在多个元素时候,动画交错开,而不是一起。

Angular动画——路由动画及高阶动画函数的更多相关文章

  1. 函数高阶(函数,改变函数this指向,高阶函数,闭包,递归)

    一.函数的定义方式 1.函数声明方式 function  关键字(命名函数) 2.函数表达式(匿名函数) 3.new  Function( ) var  fn = new  Function(‘参数1 ...

  2. 从 ES6 高阶箭头函数理解函数柯里化

    前言:第一次看到多个连续箭头函数是在一个 react 项目中,然鹅确认了下眼神,并不是对的人,因为看得一脸懵逼.em......于是开始各种搜索,先是知道了多个连续箭头函数就是 es6 的多次柯里化的 ...

  3. JS高阶---IIFE&&函数前加;

    IIFE( 立即调用函数表达式)是一个在定义时就会立即执行的 JavaScript 函数. 全称为Immediately Invoked Function Expression 有时如果不加:会出现一 ...

  4. JS高阶---回调函数

    1.什么函数是回调函数? 此时两者的执行并没有先后顺序 两个都是回调函数 满足三个特点就是回调 .定义了函数 .没有主动调用 .最后执行了 2.常见的回调函数有哪些? .DOM事件回调函数 .定时器回 ...

  5. Hive高阶聚合函数 GROUPING SETS、Cube、Rollup

    -- GROUPING SETS作为GROUP BY的子句,允许开发人员在GROUP BY语句后面指定多个统计选项,可以简单理解为多条group by语句通过union all把查询结果聚合起来结合起 ...

  6. react_结合 redux - 高阶函数 - 高阶组件 - 前端、后台项目打包运行

    Redux 独立的集中式状态管理 js 库 - 参见 My Git 不是 react 库,可以与 angular.vue 配合使用,通常和 react 用 yarn add redux import ...

  7. react高阶组件的一些运用

    今天学习了react高阶组件,刚接触react学习起来还是比较困难,和大家分享一下今天学习的知识吧,另外缺少的地方欢迎补充哈哈 高阶组件(Higher Order Components,简称:HOC) ...

  8. Scheme 4 Javaer-3.高阶函数

    1.3  Formulating Abstractions with Higher-Order Procedures 教材有时候依照学生的基础.从0讲起:有时候给出一个大图,然后具体地逐一介绍. 本文 ...

  9. 高阶组件(Higher-Order Components)

    有时候人们很喜欢造一些名字很吓人的名词,让人一听这个名词就觉得自己不可能学会,从而让人望而却步.但是其实这些名词背后所代表的东西其实很简单. 我不能说高阶组件就是这么一个东西.但是它是一个概念上很简单 ...

随机推荐

  1. MySQL物理备份 lvm-snapshot

    MySQL备份之 lvm-snapshot lvm-snapshot(工具备份) 优点: 几乎是热备(穿件快照前把表上锁,创建完成后立即释放) 支持所有引擎 备份速度快 无需使用昂贵的商业软件(它是操 ...

  2. Django视图

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  3. [CTSC2017]网络

    [CTSC2017]网络 连一条长度为len的边,使得基环树的直径最小 结论:一定连在某条直径两个点上(否则更靠近不劣) 然后二分答案判定. dp[i]:链上一个点往下延伸的最大深度 考虑对于任意两个 ...

  4. work behind corp proxy

    =================================proxy 的写法=================================一般写法是: http://my.proxy.ad ...

  5. 关于读取XML文件代码【学习笔记】

    public class XmlManager { private XmlDocument m_XMLDoc = null; public XmlManager(XmlDocument xmldoc) ...

  6. Spring.Net 入门学习笔记-----one

    一. 基本概念    Spring.Net是一个轻量级的控制反转(Ioc)和面向切面的(Aop)的容器框架: Ioc:控制反转:简单的说就是将创建对象的控制权转交给外部容器(IApplicationC ...

  7. Selenium for C#(一) 环境安装

    Selenium 环境安装 本地环境为VS2015,由于selenium 官网不知什么原因打不开. 特记录下VS上使用NuGet安装Selenium的步骤. 利用Package Manager Con ...

  8. java多线程基础篇第一篇

    1.在开始多线程之前,我们先来聊聊计算机的缓存 计算机处理一个程序需要cpu处理器与存储设备的交互.但是在计算机发展的过程中,cpu处理器的处理速度不断提高,而存储设备的读写速度却没有得到与cpu同样 ...

  9. 【gitlab】gitlab快速部署教程

    gitlab快速部署教程 部署环境 Ubuntu 16.04(亲测可用) 开始部署 安装依赖 sudo apt-get install curl openssh-server ca-certifica ...

  10. react项目构建

    1.react脚手架 npm install -g create-react-app create-react-app myproject 2.页面配置(bootcdn) <script src ...