Angular動畫——路由動畫及高階動畫函數
阿新 • • 發佈:2019-02-11
.project ner ole 使用 city leave ctc direction pda
一、路由動畫
路由動畫需要在host元數據中指定觸發器。動畫註意不要過多,否則適得其反。
內容優先,引導用戶去註意到某個內容。動畫只是輔助手段。
定義一個進場動畫,一個離場動畫。
因為進場動畫和離場動畫用的特別頻繁,有一個別名叫: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 }View Codefrom "../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() } ] } ]; }View Code
定義路由
<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; }View Code
修改一下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); }); } }View Code
Stagger使得在多個元素時候,動畫交錯開,而不是一起。
Angular動畫——路由動畫及高階動畫函數