Angular 動(dòng)畫-介紹

2022-07-09 17:21 更新

Angular 動(dòng)畫簡介

動(dòng)畫用于提供運(yùn)動(dòng)的幻覺:HTML 元素隨著時(shí)間改變樣式。精心設(shè)計(jì)的動(dòng)畫可以讓你的應(yīng)用更有趣,更易用,但它們不僅僅是裝飾性的。動(dòng)畫可以通過幾種方式改善你的應(yīng)用和用戶體驗(yàn):

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

典型的動(dòng)畫會(huì)涉及多種隨時(shí)間變化的轉(zhuǎn)換。HTML 元素可以移動(dòng)、變換顏色、增加或縮小、隱藏或從頁面中滑出。這些變化可以同時(shí)發(fā)生或順序發(fā)生。你可以控制每次轉(zhuǎn)換的持續(xù)時(shí)間。

Angular 的動(dòng)畫系統(tǒng)是基于 CSS 功能構(gòu)建的,這意味著你可以 "動(dòng)" 瀏覽器認(rèn)為可動(dòng)的任何屬性。包括位置、大小、變形、顏色、邊框等。W3C 在它的 CSS Transitions(轉(zhuǎn)場) 頁中維護(hù)了一個(gè)可動(dòng)屬性的列表。

關(guān)于本指南

本指南覆蓋了基本的 Angular 動(dòng)畫特性,讓你能開始為你的項(xiàng)目添加 Angular 動(dòng)畫。

本指南中描述的特性,以及相關(guān)的 Angular 動(dòng)畫章節(jié)中描述的更多高級(jí)特性,都在一個(gè)范例 現(xiàn)場演練 / 下載范例 中進(jìn)行了演示。

快速上手

Angular 主要的動(dòng)畫模塊是 ?@angular/animations? 和 ?@angular/platform-browser?。當(dāng)你使用 CLI 創(chuàng)建新項(xiàng)目時(shí),這些依賴會(huì)自動(dòng)添加到你的項(xiàng)目中。

為了把 Angular 動(dòng)畫添加到你的項(xiàng)目中,把這些與動(dòng)畫相關(guān)的模塊和標(biāo)準(zhǔn)的 Angular 功能一起導(dǎo)入進(jìn)來。

步驟一:啟用動(dòng)畫模塊

導(dǎo)入 ?BrowserAnimationsModule?,它能把動(dòng)畫能力引入 Angular 應(yīng)用的根模塊中。

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 { }
注意:
當(dāng)你使用 CLI 創(chuàng)建應(yīng)用時(shí),應(yīng)用的根模塊 ?app.module.ts? 位于 ?src/app? 目錄下。

步驟二:把動(dòng)畫功能導(dǎo)入組件文件中

如果你準(zhǔn)備在組件文件中使用特定的動(dòng)畫函數(shù),請(qǐng)從 ?@angular/animations? 中導(dǎo)入這些函數(shù)。

import { Component, HostBinding } from '@angular/core';
import {
  trigger,
  state,
  style,
  animate,
  transition,
  // ...
} from '@angular/animations';

步驟三:添加動(dòng)畫的元數(shù)據(jù)屬性

在組件的 ?@Component()? 裝飾器中,添加一個(gè)名叫 ?animations:? 的元數(shù)據(jù)屬性。你可以把用來定義動(dòng)畫的觸發(fā)器放進(jìn) ?animations ?元數(shù)據(jù)屬性中。

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  animations: [
    // animation triggers go here
  ]
})

轉(zhuǎn)場動(dòng)畫

我們來做一個(gè)簡單的轉(zhuǎn)場動(dòng)作,它把單個(gè) HTML 元素從一個(gè)狀態(tài)變成另一個(gè)狀態(tài)。比如,你可以指定按鈕根據(jù)用戶的最后一個(gè)動(dòng)作顯示成OpenClosed狀態(tài)。當(dāng)按鈕處于 ?open ?狀態(tài)時(shí),它是可見的,并且是黃色的。當(dāng)它處于 ?closed ?狀態(tài)時(shí),它是透明的,并且是藍(lán)色的。

在 HTML 中,這些屬性都使用普通的 CSS 樣式,比如顏色(color)和透明度(opacity)。在 Angular 中,使用 ?style()? 函數(shù)來指定一組用作動(dòng)畫的 CSS 樣式??梢詾閯?dòng)畫狀態(tài)指定一組樣式,并為該狀態(tài)指定一個(gè)名字,比如 ?open ?或 ?closed?。

我們創(chuàng)建一個(gè)具有簡單轉(zhuǎn)場動(dòng)畫的 ?open-close? 組件。
在終端窗口運(yùn)行下列命令以生成該組件:
ng g component open-close

這會(huì)在 ?src/app/open-close.component.ts? 下創(chuàng)建此組件。

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

使用 Angular 的 ?state()? 函數(shù)來定義不同的狀態(tài),供每次轉(zhuǎn)場結(jié)束時(shí)調(diào)用。該函數(shù)接受兩個(gè)參數(shù):一個(gè)唯一的名字,比如 ?open ?或 ?closed ?和一個(gè) ?style()? 函數(shù)。

使用 ?style()? 函數(shù)來定義一組與指定的狀態(tài)名相關(guān)的樣式。名稱里帶中線的樣式屬性必須是小駝峰 格式的,如 ?backgroundColor?,或者把它們包裹到引號(hào)里,如 ?'background-color'?。

我們來看看 Angular 的 ?state()? 函數(shù)如何與 ?style()? 函數(shù)聯(lián)用,來設(shè)置 CSS 樣式的屬性。 在下面的代碼片段中,該狀態(tài)的多個(gè)樣式屬性都是同時(shí)設(shè)置的。在 ?open ?狀態(tài)中,該按鈕的高度是 200 像素,透明度是 1,背景色是黃色。

// ...
state('open', style({
  height: '200px',
  opacity: 1,
  backgroundColor: 'yellow'
})),

在下面這個(gè) ?closed ?狀態(tài)中,按鈕的高度是 100 像素,透明度是 0.5,背景色是綠色。

state('closed', style({
  height: '100px',
  opacity: 0.8,
  backgroundColor: 'blue'
})),

轉(zhuǎn)場與時(shí)序

在 Angular 中,你可以設(shè)置多個(gè)樣式而不必用動(dòng)畫。不過,如果沒有進(jìn)一步細(xì)化,按鈕的轉(zhuǎn)換會(huì)立即完成 —— 沒有漸隱、沒有收縮,也沒有其它的可視化效果來指出正在發(fā)生變化。

要讓這些變化不那么突兀,就要定義一個(gè)動(dòng)畫轉(zhuǎn)場來要求這些狀態(tài)之間的變化在一段時(shí)間內(nèi)發(fā)生。?transition()? 接受兩個(gè)參數(shù):第一個(gè)參數(shù)接受一個(gè)表達(dá)式,它定義兩個(gè)轉(zhuǎn)場狀態(tài)之間的方向;第二個(gè)參數(shù)接受一個(gè)或一系列 ?animate()? 函數(shù)。

使用 ?animate()? 函數(shù)來定義長度、延遲和緩動(dòng)效果,并指定一個(gè)樣式函數(shù),以定義轉(zhuǎn)場過程中的樣式??梢杂?nbsp;?animate()? 函數(shù)來為多步動(dòng)畫定義 ?keyframes()? 函數(shù)。這些定義放在 ?animate()? 函數(shù)的第二個(gè)參數(shù)中。

動(dòng)畫元數(shù)據(jù):持續(xù)時(shí)間、延遲和緩動(dòng)效果

?animate()? 函數(shù)(作為轉(zhuǎn)場函數(shù)的第二個(gè)參數(shù))可以接受 ?timings ?和 ?styles ?參數(shù)。

?timings ?參數(shù)可以接受一個(gè)數(shù)字或由三部分組成的字符串。

animate (duration)

或者

animate ('duration delay easing')

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

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

第二個(gè)參數(shù) ?delay ?的語法和 ?duration ?一樣。比如:

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

第三個(gè)參數(shù) ?easing ?控制動(dòng)畫在運(yùn)行期間如何進(jìn)行加速和減速。比如 ?ease-in? 表示動(dòng)畫開始時(shí)很慢,然后逐漸加速。

  • 等待 100 毫秒,運(yùn)行 200 毫秒。按照減速曲線運(yùn)動(dòng),快速啟動(dòng)并逐漸減速,直到靜止:?'0.2s 100ms ease-out' ?
  • 運(yùn)行 200 毫秒,不等待。按照標(biāo)準(zhǔn)曲線運(yùn)動(dòng),開始很慢,中間加速,最后逐漸減速:?'0.2s ease-in-out' ?
  • 立即開始,運(yùn)行 200 毫秒。按照加速曲線運(yùn)動(dòng),開始很慢,最后達(dá)到全速:?'0.2s ease-in'?
注意:
有關(guān)緩動(dòng)曲線的一般信息,參閱 Material Design 網(wǎng)站上關(guān)于自然緩動(dòng)曲線的主題。

下面的例子提供了一個(gè)從 ?open ?到 ?closed ?的持續(xù)一秒的狀態(tài)轉(zhuǎn)場。

transition('open => closed', [
  animate('1s')
]),

在上面的代碼片段中,?=>? 操作符表示單向轉(zhuǎn)場,而 ?<=>? 表示雙向轉(zhuǎn)場。在轉(zhuǎn)場過程中,?animate()? 指定了轉(zhuǎn)場需要花費(fèi)的時(shí)間。在這里,從 ?open ?到 ?closed ?狀態(tài)的轉(zhuǎn)換要花費(fèi) 1 秒中,表示成 ?1s?。

下面的例子添加了一個(gè)從 ?closed ?到 ?open ?的狀態(tài)轉(zhuǎn)場,轉(zhuǎn)場動(dòng)畫持續(xù) 0.5 秒。

transition('closed => open', [
  animate('0.5s')
]),
注意:
在 ?state ?和 ?transition ?函數(shù)中使用樣式時(shí)有一些需要注意的地方。
  • 請(qǐng)用 ?state()? 來定義那些每個(gè)轉(zhuǎn)場結(jié)束時(shí)的樣式,這些樣式在動(dòng)畫完成后仍會(huì)保留
  • 使用 ?transition()? 來定義那些中間樣式,以便在動(dòng)畫過程中產(chǎn)生運(yùn)動(dòng)的錯(cuò)覺
  • 當(dāng)禁用了動(dòng)畫時(shí),也會(huì)忽略 ?transition()? 中的樣式,但 ?state()? 中的樣式不會(huì)。
  • 在同一個(gè) ?transition()? 參數(shù)中包含多個(gè)狀態(tài)對(duì):
transition( 'on => off, off => void' )

觸發(fā)動(dòng)畫

動(dòng)畫需要觸發(fā)器,以便知道該在何時(shí)開始。?trigger()? 函數(shù)會(huì)把一些狀態(tài)和轉(zhuǎn)場組合在一起,并為這個(gè)動(dòng)畫命名,這樣你就可以在 HTML 模板中把它附加到想要觸發(fā)動(dòng)畫的元素上了。

?trigger()? 函數(shù)描述了監(jiān)聽變化時(shí)要使用的觸發(fā)器名稱。當(dāng)這個(gè)觸發(fā)器名稱所綁定的值發(fā)生了變化時(shí),觸發(fā)器就會(huì)啟動(dòng)它所定義的操作。這些操作可能是轉(zhuǎn)場,也可能是其它功能,我們稍后就會(huì)看到。

在這個(gè)例子中,我們將把該觸發(fā)器命名為 ?openClose?,并把它附加到 ?button ?元素上。該觸發(fā)器描述了 ?open ?和 ?closed ?兩個(gè)狀態(tài),以及兩個(gè)轉(zhuǎn)場效果的時(shí)序。

注意:
在每個(gè) ?trigger()? 函數(shù)調(diào)用中,元素在任意時(shí)刻只能處于其中的一個(gè)狀態(tài)。但是,元素可以在同一時(shí)刻激活多個(gè)觸發(fā)器。

定義動(dòng)畫,并把它們附加到 HTML 模板中

這些控制 HTML 元素如何運(yùn)動(dòng)的動(dòng)畫是在組件的元數(shù)據(jù)中定義的。請(qǐng)?jiān)?nbsp;?@Component()? 裝飾器的 ?animations:? 屬性下用代碼定義你要用的動(dòng)畫。

@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;
  }

}

為組件定義好這些動(dòng)畫觸發(fā)器之后,你可以給觸發(fā)器名稱加上 ?@? 前綴并包在方括號(hào)里,來把它附加到組件模板中的元素上。然后,你可以使用 Angular 的標(biāo)準(zhǔn)屬性綁定語法(如下所示),來把這個(gè)觸發(fā)器綁定到模板表達(dá)式上。這里的 ?triggerName ?就是觸發(fā)器的名稱,而 ?expression ?的求值結(jié)果是前面定義過的動(dòng)畫狀態(tài)之一。

<div [@triggerName]="expression">…</div>;

當(dāng)該表達(dá)式的值變成了新的狀態(tài)時(shí),動(dòng)畫就會(huì)執(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>

在這個(gè)例子中,當(dāng) ?isOpen ?表達(dá)式求值為一個(gè)已定義狀態(tài) ?open ?或 ?closed ?時(shí),就會(huì)通知 ?openClose ?觸發(fā)器說狀態(tài)變化了。然后,就由 ?openClose ?中的代碼來處理狀態(tài)變更,并啟動(dòng)狀態(tài)變更動(dòng)畫。

對(duì)于那些進(jìn)入或離開頁面的元素(插入到 DOM 中或從中移除),你可以讓動(dòng)畫變成有條件的。比如,在 HTML 模板中可以和 ?*ngIf? 一起使用動(dòng)畫觸發(fā)器。

注意:
在組件文件中,要把用來定義動(dòng)畫的觸發(fā)器設(shè)置為 ?@Component()? 裝飾器的 ?animations:? 屬性的值。
在 HTML 模板文件中,使用這個(gè)觸發(fā)器的名稱來把所定義的這些動(dòng)畫附加到想要添加動(dòng)畫的 HTML 元素上。

代碼回顧

下面是轉(zhuǎn)場動(dòng)畫范例中討論過的代碼文件。

  • 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;
    }

動(dòng)畫 API 小結(jié)

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

函數(shù)名

用途

trigger()

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

style()

定義一個(gè)或多個(gè)要用于動(dòng)畫中的 CSS 樣式。用于在動(dòng)畫期間控制 HTML 元素的視覺外觀。要使用對(duì)象語法。

?state()?

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

animate()

指定轉(zhuǎn)場的時(shí)序信息。delay 和 easing 是可選值。其中可以包含 style() 調(diào)用。

transition()

定義兩個(gè)命名狀態(tài)之間的動(dòng)畫序列。使用數(shù)組語法。

keyframes()

允許以特定的時(shí)間間隔對(duì)樣式進(jìn)行順序更改。用于 animate() 中。每個(gè) keyframe() 中都可以包含多個(gè) style() 調(diào)用。使用數(shù)組語法。

?group()?

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

query()

找出當(dāng)前元素中的一個(gè)或多個(gè)內(nèi)部 HTML 元素。

sequence()

指定一個(gè)動(dòng)畫步驟列表,它們會(huì)逐個(gè)順序執(zhí)行。

stagger()

交錯(cuò)安排多元素動(dòng)畫的開始時(shí)間。

animation()

生成可在其它地方調(diào)用的可復(fù)用動(dòng)畫。與 useAnimation() 一起使用。

useAnimation()

激活一個(gè)可復(fù)用動(dòng)畫。和 animation() 一起使用。

animateChild()

允許子組件上的動(dòng)畫和父組件在同一個(gè)時(shí)間范圍(timeframe)內(nèi)執(zhí)行。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)