Angular Animation添加UI活潑的互動性
羅慧真 Anita Lo
- 精誠資訊/恆逸教育訓練中心-資深講師
- 技術分類:程式設計
App增添一些動畫效果不只是讓畫面變得好看,它還能幫助使用者更直覺地理解您的應用程式在做什麼。透過漸變、滑動、縮放等動畫效果,使用者可以感受到操作的回饋,讓介面看起來更自然、更有互動性。這一篇文章將透過一個簡單的範例,教您如何在Angular中使用Animation API做一個可開關顯示區塊的動畫元件。
Angular Animation是什麼?
Angular提供了內建的動畫API,讓您可以不依賴外部動畫函式庫,就能在元件中定義並控制動畫行為。這些動畫透過 @angular/animations 提供的一組函式來實現,其中包括:
- trigger():定義一個動畫名稱與邏輯
- state():定義動畫狀態與對應的樣式
- style():指定 CSS 樣式
- transition():描述狀態轉換與動畫時間
- animate():控制動畫執行時長與緩動曲線
Angular Animation特別適合用於:
- 展開/收合區塊
- 加入/移除元件
- 頁面切換與過場
- 表單驗證與提示互動
您可以在元件的 @Component() 中,透過 animations: [] 區塊來註冊動畫邏輯。
接下來這個範例將帶您學會類似手風琴式的開關區塊效果,如下圖:

建置動畫的第一步
本範例是使用Angular 19 的環境建立專案,若您想試試看,建議至少使用 Angular 18 以上的版本,因為範例使用了 signal API 的相關函式:
ng new animatTips --minimal
首先,您需要在專案的 providers 宣告要使用的動畫元件,開啟 app.config.ts 在 providers 陣列中加入 provideAnimationsAsync() ,並匯入 provideAnimationsAsync() 的來源:
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideAnimationsAsync(), provideRouter(routes) ] };
預備動畫元件
接著加入一個元件作為動畫元件:
ng g c box
修改 box.component.ts 內容如下,這是基本HTML內容並不具備動畫能力:
import { Component, computed, model } from '@angular/core'; @Component({ selector: 'app-box', imports: [], template: ` <div>boxState: {{ boxState() }}</div> @if (opened()){ <div style="width: 500px; height: 300px; background-color: lightgray; box-shadow: 2px 2px 5px gray;"> Hello </div> } `, styles:[] ] }) export class BoxComponent { opened = model(true); boxState = computed(() => this.opened() ? 'open' : 'closed'); }
- opened,是一個使用 model
(true) 初始化的屬性。這表示它是一個signal 的布林值模型,初始值為 true。model() 是 signal api 的功能之一,代表在元件中可input/output 的屬性,當該值改變時,會自動通知依賴它的其他部分進行更新。 - boxState,是一個根據 opened 訊號變更時衍生的計算結果。computed() 是signal api 的功能之一,會根據另一個 signal 變數改變時進行計算。
在 app.component.ts 中使用 app-box,內容如下:
import { Component, computed, signal } from '@angular/core'; import { BoxComponent } from './box/box.component'; @Component({ selector: 'app-root', imports: [BoxComponent], template: ` <button (click)="toggle()">toggle </button> <app-box [opened]="isOpen()" ></app-box>`, styles:[] }) export class AppComponent { title = 'AnimationBasic'; isOpen = signal<boolean>(false); toggle() { this.isOpen.update((o)=>!o) ; } }
- isOpen,是可寫入式的boolean訊號,預設值為 false 。
- toggle(),是 button 按鈕的click 事件處理函示,控制 isOpen 的 true/false 變化,isOpen 是 signal 可寫變數,要使用 update () 函示進行變更 isOpen 的值。
- <app-box [opened]="isOpen()" ></app-box> , isOpen 的值最後會帶入 app-box 的 opened 屬性。
使用 以下命令啟動程式:
ng s -o
結果如下,目前沒有任何動畫效果:

加入動畫效果
這個範例會有兩個狀態,一個是 open 、 一個是 closed ,當狀態改變時要改變style:
- open 狀態, style 高度要調整為 300px ,不透明效果
- closed 狀態, style 高度要調整為 0px ,完全透明效果
接下來修改 box.component.ts ,註記 @if (..) { ,,, } 區段,重新加入 div 區段:
@Component({ selector: 'app-box', imports: [], template: ` <div [@openClose]="boxState()" style="width: 500px; height: 300px; background-color: lightgray; box-shadow: 2px 2px 5px gray;"> Hello </div> <!-- <div>boxState: {{ boxState() }}</div> @if (opened()){ <div style="width: 500px; height: 300px; background-color: lightgray; box-shadow: 2px 2px 5px gray;"> Hello </div> } --> `, styles: [], animations: [ trigger('openClose', [ state( 'open', style({ height: '300px', opacity: 1 }), ), state( 'closed', style({ height: '0px', opacity: 0 }), ), ]) ] })
在 @Component 加入 animations 區段,陣列內加入一個成員 trigger() 。 trigger() 是宣告動畫觸發的名稱以及行為,第一個參數是 trigger 的名稱 -- openClose,第二個參數傳入則是動畫的元素,像是 state 、 transition 。 state() ,是動畫的狀態,第一個參數是狀態名稱,第二個參數會建立一組 CSS 樣式,用於當滿足此狀態時套用該樣式。 這個範例如上所述有兩個狀態,所以我們在 trigger 第二個參數中傳入兩個動畫元素,也就是 open / closed 狀態。
[@openClose], div 中的指令 @openClose 會對應到 trigger 的名稱,這裡傳入 boxState() ,它會根據opened布林訊號的改變計算值為 open 或是 closed 。因此觸動 trigger 中的 state 條件套用該 style 樣式。
加入動畫元素之後效果如下:

這樣的結果並不讓人滿意,最基本的動畫效果 … 感覺上要有一種慢慢變成 … 某種樣子,在此加一點轉場的效果,動畫味就十足了。
修改 animations 區段,在 trigger 的第二個參數陣列組中加入 transition:
@Component({
… 內容省略 …
animations: [
trigger('openClose', [
state(
'open',
style({ height: '300px', opacity: 1 }),
),
state(
'closed',
style({ height: '0px', opacity: 0 }),
) ,
transition('open <=> closed', [animate('1s')])
])
]
})
transition(),是動畫元素之一,用來處理轉場效果,也就是 狀態A 到 狀態B 要花費的時間 (使用 animate 設定時間) ,這個範例的狀態是 open / closed ,這兩個狀態的中間符號可以是 => 、 <= 、 <=> ,這樣的符號應該很容易識讀,在此我們使用雙向箭頭「<=>」,代表不論是 open 到 closed 或是 closed 到 open ,第二個參數傳入的則是轉場完成的時間,這裡設定 1s,就是一秒的時間。
此時執行的結果將會是:

這個範例只是起點,未來您還可以加入滑動動畫、列表排序、頁面轉場等,讓使用者介面更具吸引力與互動性。更多關於Angular 動畫資訊可參考Angular官網(也是本篇文章的參考資源)
若您對於學習Angular有更多的興趣,歡迎參考以下課程可以了解更多的技巧喔!