Angular 動畫-介紹

2022-07-09 17:21 更新

Angular 動畫簡介

動畫用于提供運動的幻覺:HTML 元素隨著時間改變樣式。精心設計的動畫可以讓你的應用更有趣,更易用,但它們不僅僅是裝飾性的。動畫可以通過幾種方式改善你的應用和用戶體驗:

  • 沒有動畫,Web 頁面的轉場就會顯得突兀、不協(xié)調
  • 運動能極大地提升用戶體驗,因此動畫可以讓用戶察覺到應用對他們的操作做出了響應
  • 良好的動畫可以直觀的把用戶的注意力吸引到要留意的地方

典型的動畫會涉及多種隨時間變化的轉換。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)。比如,你可以指定按鈕根據用戶的最后一個動作顯示成OpenClosed狀態(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)建此組件。

動畫狀態(tài)和樣式

使用 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()? 函數的第二個參數中。

動畫元數據:持續(xù)時間、延遲和緩動效果

?animate()? 函數(作為轉場函數的第二個參數)可以接受 ?timings ?和 ?styles ?參數。

?timings ?參數可以接受一個數字或由三部分組成的字符串。

animate (duration)

或者

animate ('duration delay easing')

第一部分 ?duration?(持續(xù)時間)是必須的。這個持續(xù)時間可以表示成一個不帶引號的純數字(表示毫秒),或一個帶引號的有單位的時間(表示秒數)。比如,0.1 秒的持續(xù)時間有如下表示方式:

  • 作為純數字,毫秒為單位:?100 ?
  • 作為字符串,毫秒為單位:?'100ms' ?
  • 作為字符串,秒為單位:?'0.1s'?

第二個參數 ?delay ?的語法和 ?duration ?一樣。比如:

  • 等待 100 毫秒,然后運行 200 毫秒表示為:?'0.2s 100ms'?

第三個參數 ?easing ?控制動畫在運行期間如何進行加速和減速。比如 ?ease-in? 表示動畫開始時很慢,然后逐漸加速。

  • 等待 100 毫秒,運行 200 毫秒。按照減速曲線運動,快速啟動并逐漸減速,直到靜止:?'0.2s 100ms ease-out' ?
  • 運行 200 毫秒,不等待。按照標準曲線運動,開始很慢,中間加速,最后逐漸減速:?'0.2s ease-in-out' ?
  • 立即開始,運行 200 毫秒。按照加速曲線運動,開始很慢,最后達到全速:?'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ā)動畫

動畫需要觸發(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 模板中

這些控制 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 元素上。

代碼回顧

下面是轉場動畫范例中討論過的代碼文件。

  • src/app/open-close.component.ts
  • @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;
      }
    
    }
  • src/app/open-close.component.html
  • <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>
  • src/app/open-close.component.css
  • :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;
    }

動畫 API 小結

?@angular/animations? 模塊提供的這些功能性 API 提供了一種領域特定語言(DSL),用于在 Angular 應用中創(chuàng)建和控制動畫效果。

函數名

用途

trigger()

開始動畫,并充當所有其它動畫函數的容器。HTML 模板可以綁定到 triggerName。使用第一個參數來聲明唯一的觸發(fā)器名稱。要使用數組語法。

style()

定義一個或多個要用于動畫中的 CSS 樣式。用于在動畫期間控制 HTML 元素的視覺外觀。要使用對象語法。

?state()?

創(chuàng)建一組有名字的 CSS 樣式,它會在成功轉換到指定的狀態(tài)時應用到元素上。該狀態(tài)可以在其它動畫函數中通過名字進行引用。

animate()

指定轉場的時序信息。delay 和 easing 是可選值。其中可以包含 style() 調用。

transition()

定義兩個命名狀態(tài)之間的動畫序列。使用數組語法。

keyframes()

允許以特定的時間間隔對樣式進行順序更改。用于 animate() 中。每個 keyframe() 中都可以包含多個 style() 調用。使用數組語法。

?group()?

指定要并行運行的一組動畫步驟(內部動畫)。該動畫只有當所有內部動畫步驟都完成之后才會繼續(xù)。用于 sequence() 或 transition() 中。

query()

找出當前元素中的一個或多個內部 HTML 元素。

sequence()

指定一個動畫步驟列表,它們會逐個順序執(zhí)行。

stagger()

交錯安排多元素動畫的開始時間。

animation()

生成可在其它地方調用的可復用動畫。與 useAnimation() 一起使用。

useAnimation()

激活一個可復用動畫。和 animation() 一起使用。

animateChild()

允許子組件上的動畫和父組件在同一個時間范圍(timeframe)內執(zhí)行。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號