您知道 Angular 包含一個複雜的動畫系統嗎?當我想要在元素進入螢幕或被破壞時為其設置動畫時,我發現它特別有用!
此外,您還可以使用 AnimationBuilder 來強製播放、暫停或停止一些自訂動畫!讓我們看看它是如何完成的。
在本練習中,我們先建立一個列表,如下所示:
@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li>{{ user.name }}</li> } </ul> `, }) export class AppComponent { users = signal<User[]>([ { id: Math.random(), name: 'Michele' } ]); addUser() { this.users.update(users => [...users, { id: Math.random(), name: 'New user' }]); } }
請注意,我們新增了一個將使用者加入清單的按鈕!
現在,如果我們想要為要新增的使用者設定動畫該怎麼辦?首先,我們想透過在主配置中提供它來告訴 Angular 我們想要使用它的動畫系統:
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; bootstrapApplication(AppComponent, { providers: [ provideAnimationsAsync(), ] });
然後,我們可以創建我們的動畫:
import { trigger, transition, style, animate } from '@angular/animations'; const fadeInAnimation = trigger('fadeIn', [ transition(':enter', [ style({ transform: 'scale(0.5)', opacity: 0 }), animate( '.3s cubic-bezier(.8, -0.6, 0.2, 1.5)', style({ transform: 'scale(1)', opacity: 1 }) ) ]) ])
有了這些幫助者,我們:
更多關於如何編寫動畫的信息,可以參考官方指南,非常棒!
現在讓我們將此動畫應用到清單中的每個元素:
@Component({ ..., template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn>{{ user.name }}</li> <!-- Notice here --> } </ul> `, // Also, add the animation to the metadata of the component animations: [fadeInAnimation] })
現在,當新增項目時,它會變得動畫!我們的第一步已經完成。
請注意,為了讓我們的動畫正常工作,Angular 必須追蹤for 中的每個元素,因為否則它最終可能會在更新模板時重新創建相同的元素,從而導致不必要的結果動畫。這是免費的新控制流語法,因為 track 屬性是強制性的,但如果您使用舊版本的 Angular 和 *ngFor 指令,則必須使用 trackBy 選項,如下所示:
<li *ngFor="let user of users; trackBy: trackByUserId" @fadeIn >{{ user.name }}</li>
// A class method in your component: trackByUserId(index, user: User) { return user.id; }
現在,讓我們在清單中加入另一種類型的動畫。
讓我們為清單的每個元素新增一個按鈕:
<li @fadeIn> {{ user.name }} <button>Make me blink</button> </li>
想像一下:我們想讓元素在按下按鈕時閃爍。那就太酷了!這就是 AnimationBuilder 服務的用武之地。
首先,讓我們建立一個將應用於每個元素的指令。在此指令中,我們將注入 ElementRef 和 AnimationBuilder:
import { AnimationBuilder, style, animate } from '@angular/animations'; @Directive({ selector: '[blink]', exportAs: 'blink', // <--- Notice standalone: true }) export class BlinkDirective { private animationBuilder = inject(AnimationBuilder); private el = inject(ElementRef); }
請注意,我們導出了指令:我們將在幾秒鐘內找到原因。
然後,我們可以創建一個像這樣的自訂動畫:
export class BlinkDirective { ... private animation = this.animationBuilder.build([ style({ transform: 'scale(1)', opacity: 1 }), animate(150, style({ transform: 'scale(1.1)', opacity: .5 })), animate(150, style({ transform: 'scale(1)', opacity: 1 })) ]); }
我們使用的函數與先前的動畫中使用的函數相同,只是樣式不同。
現在我們要建立一個播放器,它將在我們的元素上執行動畫:
export class BlinkDirective { ... private player = this.animation.create(this.el.nativeElement); }
現在讓我們公開一個真正啟動動畫的方法!
export class BlinkDirective { ... start() { this.player.play(); } }
只剩下一步了:我們必須導入指令,將其應用到我們的元素,使用模板變數獲取它,並在按下按鈕時調用該方法!
@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn blink #blinkDir="blink"> {{ user.name }} <button (click)="blinkDir.start()">Make me blink</button> </li> } </ul> `, imports: [BlinkDirective], animations: [ fadeInAnimation ] })
我們可以取得指令的實例並將其放入局部變數中,因為我們之前使用exportAs導出了指令。這就是關鍵部分!
現在,嘗試點擊按鈕:該元素應該正確動畫!
練習已經完成,但這只是冰山一角! AnimationPlayer 有許多指令可用於停止、暫停和恢復動畫。非常酷!
interface AnimationPlayer { onDone(fn: () => void): void; onStart(fn: () => void): void; onDestroy(fn: () => void): void; init(): void; hasStarted(): boolean; play(): void; pause(): void; restart(): void; finish(): void; destroy(): void; reset(): void; setPosition(position: number): void; getPosition(): number; parentPlayer: AnimationPlayer; readonly totalTime: number; beforeDestroy?: () => any; }
如果您想使用它,這是我們的完整範例:只需將其放入 main.ts 檔案中並查看它的實際效果!
import { Component, signal, Directive, ElementRef, inject } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { trigger, transition, style, animate, AnimationBuilder } from '@angular/animations'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; interface User { id: number; name: string; } @Directive({ selector: '[blink]', exportAs: 'blink', standalone: true }) export class BlinkDirective { private animationBuilder = inject(AnimationBuilder); private el = inject(ElementRef); private animation = this.animationBuilder.build([ style({ transform: 'scale(1)', opacity: 1 }), animate(150, style({ transform: 'scale(1.1)', opacity: .5 })), animate(150, style({ transform: 'scale(1)', opacity: 1 })) ]); private player = this.animation.create(this.el.nativeElement); start() { this.player.play(); } } const fadeInAnimation = trigger('fadeIn', [ transition(':enter', [ style({ transform: 'scale(0.5)', opacity: 0 }), animate( '.3s cubic-bezier(.8, -0.6, 0.2, 1.5)', style({ transform: 'scale(1)', opacity: 1 }) ) ]) ]) @Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn blink #blinkDir="blink"> {{ user.name }} <button (click)="blinkDir.start()">Make me blink</button> </li> } </ul> `, imports: [BlinkDirective], animations: [ fadeInAnimation ] }) export class App { users = signal([ { id: Math.random(), name: 'Michele' } ]); addUser() { this.users.update(users => [...users, { id: Math.random(), name: 'New user' }]); } } bootstrapApplication(App, { providers: [ provideAnimationsAsync() ] });
以上是Angular LAB:動畫列表並使用 AnimationBuilder 實作命令式動畫的詳細內容。更多資訊請關注PHP中文網其他相關文章!