目录
一、路由动画二、Group三、Query & Stagger
一、路由动画
路由动画需要在host元数据中指定触发器。动画注意不要过多,否则适得其反。
内容优先,引导用户去注意到某个内容。动画只是辅助手段。
在router.animate.ts中定义一个进场动画,一个离场动画。
因为进场动画和离场动画用的特别频繁,有一个别名叫:enter和:leave。
import { trigger, state, transition, style, animate} from \'@angular/animations\'; export const slideToRight = trigger(\'routeAnim\',[ state(\'void\',style({\'position\':\'fixed\',\'width\':\'100%\',\'height\':\'100%\'})), state(\'*\',style({\'position\':\'fixed\',\'width\':\'100%\',\'height\':\'80%\'})), transition(\'void => *\',[ style({transform:\'translateX(-100%)\'}), animate(\'.5s ease-in-out\', style({transform:\'translateX(0)\'})) ]), transition(\'* => void\',[ style({transform:\'translateX(0)\'}), animate(\'.5s ease-in-out\', style({transform:\'translateX(100%)\'})) ]), ]);
在project-list中使用路由动画。
import { Component, OnInit , HostBinding } from \"@angular/core\"; import { MatDialog } from \"@angular/material\"; import { NewProjectComponent } from \"../new-project/new-project.component\"; import { InviteComponent } from \'../invite/invite.component\'; import { ConfirmDialogComponent } from \'../../shared/confirm-dialog/confirm-dialog.component\'; import {slideToRight} from \'../../animate/router.animate\' @Component({ selector: \"app-project-list\", templateUrl: \"./project-list.component.html\", styleUrls: [\"./project-list.component.scss\"], animations:[ slideToRight ] }) export class ProjectListComponent implements OnInit { @HostBinding(\'@routeAnim\') state; projects = [ { name: \"企业协作平台\", desc: \"这是一个企业内部项目\", coverImg: \"assets/images/covers/0.jpg\" }, { name: \"自动化测试项目\", desc: \"这是一个企业内部项目\", coverImg: \"assets/images/covers/2.jpg\" } ]; constructor(private dialog: MatDialog) { } ngOnInit() { } openNewProjectDialog() { // this.dialog.open(NewProjectComponent,{data:\'this is a dialog\'}); const dialogRef = this.dialog.open(NewProjectComponent, { data: { title: \'新建项目\' } }); dialogRef.afterClosed().subscribe((result) => { console.log(result); }); } lauchInviteDialog() { const dialogRef = this.dialog.open(InviteComponent); } lauchUpdateDialog() { const dialogRef = this.dialog.open(NewProjectComponent, { data: { title: \'编辑项目\' } }); } lauchConfimDialog() { const dialogRef = this.dialog.open(ConfirmDialogComponent, { data: { title: \'编辑项目\', content: \'您确认删除该项目吗?\' } }); } }
在task-home中使用路由动画。
import { Component, OnInit , HostBinding } from \"@angular/core\"; import { NewTaskComponent } from \"../new-task/new-task.component\"; import { MatDialog } from \"@angular/material\"; import { CopyTaskComponent } from \"../copy-task/copy-task.component\"; import { ConfirmDialogComponent } from \"../../shared/confirm-dialog/confirm-dialog.component\"; import { NewTaskListComponent } from \"../new-task-list/new-task-list.component\"; import {slideToRight} from \'../../animate/router.animate\'; @Component({ selector: \"app-task-home\", templateUrl: \"./task-home.component.html\", styleUrls: [\"./task-home.component.scss\"], animations:[ slideToRight ] }) export class TaskHomeComponent implements OnInit { constructor(private dialog: MatDialog) {} @HostBinding(\'@routeAnim\') state; ngOnInit() {} launchNewTaskDialog() { // this.dialog.open(NewTaskComponent); const dialogRef = this.dialog.open(NewTaskComponent, { data: { title: \"新建任务\" } }); } lauchCopyTaskDialog() { const dialogRef = this.dialog.open(CopyTaskComponent, { data: { lists: this.lists } }); } launchUpdateTaskDialog(task) { const dialogRef = this.dialog.open(NewTaskComponent, { data: { title: \"修改任务\", task: task } }); } launchConfirmDialog() { const dialogRef = this.dialog.open(ConfirmDialogComponent, { data: { title: \"删除任务列表\", content: \"您确定要删除该任务列表吗?\" } }); } launchEditListDialog() { const dialogRef = this.dialog.open(NewTaskListComponent, { data: { title: \"更改列表名称\" } }); dialogRef.afterClosed().subscribe(result => console.log(result)); } launchNewListDialog() { const dialogRef = this.dialog.open(NewTaskListComponent, { data: { title: \"新建列表名称\" } }); dialogRef.afterClosed().subscribe(result => console.log(result)); } lists = [ { id: 1, name: \"待办\", tasks: [ { id: 1, desc: \"任务一: 去星巴克买咖啡\", completed: true, priority: 3, owner: { id: 1, name: \"张三\", avatar: \"avatars:svg-11\" }, dueDate: new Date(), reminder: new Date() }, { id: 2, desc: \"任务一: 完成老板布置的PPT作业\", completed: false, priority: 2, owner: { id: 2, name: \"李四\", avatar: \"avatars:svg-12\" }, dueDate: new Date() } ] }, { id: 2, name: \"进行中\", tasks: [ { id: 1, desc: \"任务三: 项目代码评审\", completed: false, priority: 1, owner: { id: 1, name: \"王五\", avatar: \"avatars:svg-13\" }, dueDate: new Date() }, { id: 2, desc: \"任务一: 制定项目计划\", completed: false, priority: 2, owner: { id: 2, name: \"李四\", avatar: \"avatars:svg-12\" }, dueDate: new Date() } ] } ]; }
定义路由
<mat-list-item [routerLink]=\"[\'/project\']\"> <mat-icon mat-list-icon svgIcon=\"projects\"></mat-icon> <h4 mat-line>项目首页</h4> <p mat-line mat-subheader> 查看您的所有项目</p> </mat-list-item> <mat-list-item [routerLink]=\"[\'/task\']\"> <mat-icon mat-list-icon svgIcon=\"projects\"></mat-icon> <h4 mat-line>任务首页</h4> <p mat-line mat-subheader> 查看您的所有项目</p> </mat-list-item>
注意:一定要用HostBinding形式。
二、Group
用于同时进行一组动画变换
group([animate(…),animate(…)…])接收一个数组,数组里写多个动画。
import { trigger, state, transition, style, animate, group} from \'@angular/animations\'; export const slideToRight = trigger(\'routeAnim\',[ state(\'void\',style({\'position\':\'fixed\',\'width\':\'100%\',\'height\':\'80%\'})), state(\'*\',style({\'position\':\'fixed\',\'width\':\'100%\',\'height\':\'80%\'})), transition(\':enter\',[ style({transform:\'translateX(-100%)\',opacity:\'0\'}), group([ animate(\'.5s ease-in-out\', style({transform:\'translateX(0)\'})), animate(\'.3s ease-in\', style({opacity:1})) ]) ]), transition(\':leave\',[ style({transform:\'translateX(0)\',opacity:\'1\'}), group([ animate(\'.5s ease-in-out\', style({transform:\'translateX(100%)\'})), animate(\'.3s ease-in\', style({opacity:0})) ]) ]), ]);
三、Query & Stagger
Query用于父节点寻找子节点,把动画应用到选中元素。非常强大。
Stagger指定有多个满足Query的元素,每个的动画之间有间隔。
做一个示例:新建的时候同时新建2个项目,两个新建出的项目的动画依次产生,第一个完成后才开始第二个。
建立list.animate.ts
进场动画,先隐藏起来,通过stagger间隔1000s做一个1s的动画。
import { trigger, state, transition, style, animate, query, animation,stagger} from \'@angular/animations\'; export const listAnimation = trigger(\'listAnim\', [ transition(\'* => *\', [ query(\':enter\', style({opacity: 0}), { optional: true }), //加入optional为true,后面的状态动画都是可选的 query(\':enter\', stagger(1000, [ animate(\'1s\', style({opacity: 1})) ]), { optional: true }), query(\':leave\', style({opacity: 1}), { optional: true }), query(\':leave\', stagger(1000, [ animate(\'1s\', style({opacity: 0})) ]), { optional: true }) ]) ]);
在project_list中使用
应用query动画一般都是跟*ngFor在一起的,需要外面套一层div。
<div class=\"container\" [@listAnim]=\"projects.length\"> <app-project-item *ngFor=\"let project of projects\" [item]=\"project\" class=\"card\" (onInvite)=\"lauchInviteDialog()\" (onEdit)=\"lauchUpdateDialog()\" (onDelete)=\"lauchConfimDialog(project)\"> </app-project-item> </div> <button class=\"ab-buttonmad-fab fab-button\" mat-fab type=\"button\" (click)=\"openNewProjectDialog()\"> <mat-icon>add</mat-icon> </button>
修改对应的css
// :host{ // display: flex; // flex-direction: row; // flex-wrap: wrap; // } //把host改为div .container{ display: flex; flex-direction: row; flex-wrap: wrap; }
修改一下component
import { Component, OnInit , HostBinding } from \"@angular/core\"; import { MatDialog } from \"@angular/material\"; import { NewProjectComponent } from \"../new-project/new-project.component\"; import { InviteComponent } from \'../invite/invite.component\'; import { ConfirmDialogComponent } from \'../../shared/confirm-dialog/confirm-dialog.component\'; import {slideToRight} from \'../../animate/router.animate\' import { listAnimation } from \'../../animate/list.animate\'; import { projection } from \'@angular/core/src/render3\'; @Component({ selector: \"app-project-list\", templateUrl: \"./project-list.component.html\", styleUrls: [\"./project-list.component.scss\"], animations:[ slideToRight,listAnimation //第一步,导入listAnimation ] }) export class ProjectListComponent implements OnInit { @HostBinding(\'@routeAnim\') state; //第二步,改造一下数组,加id projects = [ { id:1, name: \"企业协作平台\", desc: \"这是一个企业内部项目\", coverImg: \"assets/images/covers/0.jpg\" }, { id:2, name: \"自动化测试项目\", desc: \"这是一个企业内部项目\", coverImg: \"assets/images/covers/2.jpg\" } ]; constructor(private dialog: MatDialog) { } ngOnInit() { } //第三步,新增元素时hard code一下 openNewProjectDialog() { // this.dialog.open(NewProjectComponent,{data:\'this is a dialog\'}); const dialogRef = this.dialog.open(NewProjectComponent, { data: { title: \'新建项目\' } }); dialogRef.afterClosed().subscribe((result) => { console.log(result); this.projects = [...this.projects, {id:3,name:\'一个新项目\',desc:\'这是一个新项目\',coverImg:\"assets/images/covers/3.jpg\"}, {id:4,name:\'又一个新项目\',desc:\'这是又一个新项目\',coverImg:\"assets/images/covers/4.jpg\"}] }); } lauchInviteDialog() { const dialogRef = this.dialog.open(InviteComponent); } lauchUpdateDialog() { const dialogRef = this.dialog.open(NewProjectComponent, { data: { title: \'编辑项目\' } }); } //第四步,改造一下删除项目 lauchConfimDialog(project) { const dialogRef = this.dialog.open(ConfirmDialogComponent, { data: { title: \'删除项目\', content: \'您确认删除该项目吗?\' } }); dialogRef.afterClosed().subscribe(result=>{ console.log(result); this.projects=this.projects.filter(p=>p.id!=project.id); }); } }
Stagger使得在多个元素时候,动画交错开,而不是一起。
以上就是详解Angular路由动画及高阶动画函数的详细内容,更多关于Angular路由动画及高阶动画函数的资料请关注其它相关文章!
© 版权声明
THE END
暂无评论内容