一、路由动画
路由动画需要在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路由动画及高阶动画函数的资料请关注www.887551.com其它相关文章!
黄山市民网:https://www.huangshanshimin.com/