動畫用于提供運動的幻覺:HTML 元素隨著時間改變樣式。精心設計的動畫可以讓你的應用更有趣,更易用,但它們不僅僅是裝飾性的。動畫可以通過幾種方式改善你的應用和用戶體驗:
典型的動畫會涉及多種隨時間變化的轉換。HTML 元素可以移動、變換顏色、增加或縮小、隱藏或從頁面中滑出。這些變化可以同時發(fā)生或順序發(fā)生。你可以控制每次轉換的持續(xù)時間。
Angular 的動畫系統(tǒng)是基于 CSS 功能構建的,這意味著你可以 "動" 瀏覽器認為可動的任何屬性。包括位置、大小、變形、顏色、邊框等。W3C 在它的 CSS Transitions(轉場) 頁中維護了一個可動屬性的列表。
本指南覆蓋了基本的 Angular 動畫特性,讓你能開始為你的項目添加 Angular 動畫。
本指南中描述的特性,以及相關的 Angular 動畫章節(jié)中描述的更多高級特性,都在一個范例 現場演練 / 下載范例 中進行了演示。
Angular 主要的動畫模塊是 ?@angular/animations
? 和 ?@angular/platform-browser
?。當你使用 CLI 創(chuàng)建新項目時,這些依賴會自動添加到你的項目中。
為了把 Angular 動畫添加到你的項目中,把這些與動畫相關的模塊和標準的 Angular 功能一起導入進來。
導入 ?BrowserAnimationsModule
?,它能把動畫能力引入 Angular 應用的根模塊中。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule
],
declarations: [ ],
bootstrap: [ ]
})
export class AppModule { }
注意:
當你使用 CLI 創(chuàng)建應用時,應用的根模塊 ?app.module.ts
? 位于 ?src/app
? 目錄下。
如果你準備在組件文件中使用特定的動畫函數,請從 ?@angular/animations
? 中導入這些函數。
import { Component, HostBinding } from '@angular/core';
import {
trigger,
state,
style,
animate,
transition,
// ...
} from '@angular/animations';
在組件的 ?@Component()
? 裝飾器中,添加一個名叫 ?animations:
? 的元數據屬性。你可以把用來定義動畫的觸發(fā)器放進 ?animations
?元數據屬性中。
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
animations: [
// animation triggers go here
]
})
我們來做一個簡單的轉場動作,它把單個 HTML 元素從一個狀態(tài)變成另一個狀態(tài)。比如,你可以指定按鈕根據用戶的最后一個動作顯示成Open或Closed狀態(tài)。當按鈕處于 ?open
?狀態(tài)時,它是可見的,并且是黃色的。當它處于 ?closed
?狀態(tài)時,它是透明的,并且是藍色的。
在 HTML 中,這些屬性都使用普通的 CSS 樣式,比如顏色(color)和透明度(opacity)。在 Angular 中,使用 ?style()
? 函數來指定一組用作動畫的 CSS 樣式??梢詾閯赢嫚顟B(tài)指定一組樣式,并為該狀態(tài)指定一個名字,比如 ?open
?或 ?closed
?。
我們創(chuàng)建一個具有簡單轉場動畫的 ?open-close
? 組件。
在終端窗口運行下列命令以生成該組件:ng g component open-close
這會在 ?
src/app/open-close.component.ts
? 下創(chuàng)建此組件。
使用 Angular 的 ?state()
? 函數來定義不同的狀態(tài),供每次轉場結束時調用。該函數接受兩個參數:一個唯一的名字,比如 ?open
?或 ?closed
?和一個 ?style()
? 函數。
使用 ?style()
? 函數來定義一組與指定的狀態(tài)名相關的樣式。名稱里帶中線的樣式屬性必須是小駝峰 格式的,如 ?backgroundColor
?,或者把它們包裹到引號里,如 ?'background-color'
?。
我們來看看 Angular 的 ?state()
? 函數如何與 ?style()
? 函數聯(lián)用,來設置 CSS 樣式的屬性。 在下面的代碼片段中,該狀態(tài)的多個樣式屬性都是同時設置的。在 ?open
?狀態(tài)中,該按鈕的高度是 200 像素,透明度是 1,背景色是黃色。
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
在下面這個 ?closed
?狀態(tài)中,按鈕的高度是 100 像素,透明度是 0.5,背景色是綠色。
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
})),
在 Angular 中,你可以設置多個樣式而不必用動畫。不過,如果沒有進一步細化,按鈕的轉換會立即完成 —— 沒有漸隱、沒有收縮,也沒有其它的可視化效果來指出正在發(fā)生變化。
要讓這些變化不那么突兀,就要定義一個動畫轉場來要求這些狀態(tài)之間的變化在一段時間內發(fā)生。?transition()
? 接受兩個參數:第一個參數接受一個表達式,它定義兩個轉場狀態(tài)之間的方向;第二個參數接受一個或一系列 ?animate()
? 函數。
使用 ?animate()
? 函數來定義長度、延遲和緩動效果,并指定一個樣式函數,以定義轉場過程中的樣式。可以用 ?animate()
? 函數來為多步動畫定義 ?keyframes()
? 函數。這些定義放在 ?animate()
? 函數的第二個參數中。
?animate()
? 函數(作為轉場函數的第二個參數)可以接受 ?timings
?和 ?styles
?參數。
?timings
?參數可以接受一個數字或由三部分組成的字符串。
animate (duration)
或者
animate ('duration delay easing')
第一部分 ?duration
?(持續(xù)時間)是必須的。這個持續(xù)時間可以表示成一個不帶引號的純數字(表示毫秒),或一個帶引號的有單位的時間(表示秒數)。比如,0.1 秒的持續(xù)時間有如下表示方式:
100
?'100ms'
?'0.1s'
?第二個參數 ?delay
?的語法和 ?duration
?一樣。比如:
'0.2s 100ms'
?第三個參數 ?easing
?控制動畫在運行期間如何進行加速和減速。比如 ?ease-in
? 表示動畫開始時很慢,然后逐漸加速。
'0.2s 100ms ease-out'
?'0.2s ease-in-out'
?'0.2s ease-in'
?注意:
有關緩動曲線的一般信息,參閱 Material Design 網站上關于自然緩動曲線的主題。
下面的例子提供了一個從 ?open
?到 ?closed
?的持續(xù)一秒的狀態(tài)轉場。
transition('open => closed', [
animate('1s')
]),
在上面的代碼片段中,?=>
? 操作符表示單向轉場,而 ?<=>
? 表示雙向轉場。在轉場過程中,?animate()
? 指定了轉場需要花費的時間。在這里,從 ?open
?到 ?closed
?狀態(tài)的轉換要花費 1 秒中,表示成 ?1s
?。
下面的例子添加了一個從 ?closed
?到 ?open
?的狀態(tài)轉場,轉場動畫持續(xù) 0.5 秒。
transition('closed => open', [
animate('0.5s')
]),
注意:
在 ?state
?和 ?transition
?函數中使用樣式時有一些需要注意的地方。
- 請用 ?
state()
? 來定義那些每個轉場結束時的樣式,這些樣式在動畫完成后仍會保留- 使用 ?
transition()
? 來定義那些中間樣式,以便在動畫過程中產生運動的錯覺- 當禁用了動畫時,也會忽略 ?
transition()
? 中的樣式,但 ?state()
? 中的樣式不會。- 在同一個 ?
transition()
? 參數中包含多個狀態(tài)對:transition( 'on => off, off => void' )
動畫需要觸發(fā)器,以便知道該在何時開始。?trigger()
? 函數會把一些狀態(tài)和轉場組合在一起,并為這個動畫命名,這樣你就可以在 HTML 模板中把它附加到想要觸發(fā)動畫的元素上了。
?trigger()
? 函數描述了監(jiān)聽變化時要使用的觸發(fā)器名稱。當這個觸發(fā)器名稱所綁定的值發(fā)生了變化時,觸發(fā)器就會啟動它所定義的操作。這些操作可能是轉場,也可能是其它功能,我們稍后就會看到。
在這個例子中,我們將把該觸發(fā)器命名為 ?openClose
?,并把它附加到 ?button
?元素上。該觸發(fā)器描述了 ?open
?和 ?closed
?兩個狀態(tài),以及兩個轉場效果的時序。
注意:
在每個 ?trigger()
? 函數調用中,元素在任意時刻只能處于其中的一個狀態(tài)。但是,元素可以在同一時刻激活多個觸發(fā)器。
這些控制 HTML 元素如何運動的動畫是在組件的元數據中定義的。請在 ?@Component()
? 裝飾器的 ?animations:
? 屬性下用代碼定義你要用的動畫。
@Component({
selector: 'app-open-close',
animations: [
trigger('openClose', [
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
})),
transition('open => closed', [
animate('1s')
]),
transition('closed => open', [
animate('0.5s')
]),
]),
],
templateUrl: 'open-close.component.html',
styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
isOpen = true;
toggle() {
this.isOpen = !this.isOpen;
}
}
為組件定義好這些動畫觸發(fā)器之后,你可以給觸發(fā)器名稱加上 ?@
? 前綴并包在方括號里,來把它附加到組件模板中的元素上。然后,你可以使用 Angular 的標準屬性綁定語法(如下所示),來把這個觸發(fā)器綁定到模板表達式上。這里的 ?triggerName
?就是觸發(fā)器的名稱,而 ?expression
?的求值結果是前面定義過的動畫狀態(tài)之一。
<div [@triggerName]="expression">…</div>;
當該表達式的值變成了新的狀態(tài)時,動畫就會執(zhí)行或者叫觸發(fā)。
下列代碼片段把該觸發(fā)器綁定到了 ?isOpen
?屬性的值上。
<nav>
<button type="button" (click)="toggle()">Toggle Open/Close</button>
</nav>
<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>
在這個例子中,當 ?isOpen
?表達式求值為一個已定義狀態(tài) ?open
?或 ?closed
?時,就會通知 ?openClose
?觸發(fā)器說狀態(tài)變化了。然后,就由 ?openClose
?中的代碼來處理狀態(tài)變更,并啟動狀態(tài)變更動畫。
對于那些進入或離開頁面的元素(插入到 DOM 中或從中移除),你可以讓動畫變成有條件的。比如,在 HTML 模板中可以和 ?*ngIf
? 一起使用動畫觸發(fā)器。
注意:
在組件文件中,要把用來定義動畫的觸發(fā)器設置為 ?@Component()
? 裝飾器的 ?animations:
? 屬性的值。
在 HTML 模板文件中,使用這個觸發(fā)器的名稱來把所定義的這些動畫附加到想要添加動畫的 HTML 元素上。
下面是轉場動畫范例中討論過的代碼文件。
@Component({
selector: 'app-open-close',
animations: [
trigger('openClose', [
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
})),
transition('open => closed', [
animate('1s')
]),
transition('closed => open', [
animate('0.5s')
]),
]),
],
templateUrl: 'open-close.component.html',
styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
isOpen = true;
toggle() {
this.isOpen = !this.isOpen;
}
}
<nav>
<button type="button" (click)="toggle()">Toggle Open/Close</button>
</nav>
<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>
:host {
display: block;
margin-top: 1rem;
}
.open-close-container {
border: 1px solid #dddddd;
margin-top: 1em;
padding: 20px 20px 0px 20px;
color: #000000;
font-weight: bold;
font-size: 20px;
}
?@angular/animations
? 模塊提供的這些功能性 API 提供了一種領域特定語言(DSL),用于在 Angular 應用中創(chuàng)建和控制動畫效果。
函數名 |
用途 |
---|---|
trigger()
|
開始動畫,并充當所有其它動畫函數的容器。HTML 模板可以綁定到 |
style()
|
定義一個或多個要用于動畫中的 CSS 樣式。用于在動畫期間控制 HTML 元素的視覺外觀。要使用對象語法。 |
?state() ? |
創(chuàng)建一組有名字的 CSS 樣式,它會在成功轉換到指定的狀態(tài)時應用到元素上。該狀態(tài)可以在其它動畫函數中通過名字進行引用。 |
animate()
|
指定轉場的時序信息。 |
transition()
|
定義兩個命名狀態(tài)之間的動畫序列。使用數組語法。 |
keyframes()
|
允許以特定的時間間隔對樣式進行順序更改。用于 |
?group() ? |
指定要并行運行的一組動畫步驟(內部動畫)。該動畫只有當所有內部動畫步驟都完成之后才會繼續(xù)。用于 |
query()
|
找出當前元素中的一個或多個內部 HTML 元素。 |
sequence()
|
指定一個動畫步驟列表,它們會逐個順序執(zhí)行。 |
stagger()
|
交錯安排多元素動畫的開始時間。 |
animation()
|
生成可在其它地方調用的可復用動畫。與 |
useAnimation()
|
激活一個可復用動畫。和 |
animateChild()
|
允許子組件上的動畫和父組件在同一個時間范圍(timeframe)內執(zhí)行。 |
更多建議: