Angular(2+)動畫API用法詳解

動畫相關的 API 都是在 @angular/animations裏面引入的。css

import { 你想要的API } from '@angular/animations';
複製代碼

trigger : 由它觸發動畫效果,稱動畫觸發器。

function trigger(
            name: string, 
            definitions: AnimationMetadata[]  
         ):AnimationTriggerMetadata;
複製代碼
  • name

    動畫觸發器名字, 如 growWidthhtml

  • definitions

    要執行的動畫, 如css3

    [ transition("void => *", [style({opacity: 0}), animate(600, style({ opacity: 1}))] )],git

state :定義目標處於某一狀態時的樣式

function state(
            name: string, 
            styles: AnimationStyleMetadata,
            options?: {params: {[name: string]: any}}
         ):AnimationStateMetadata;
複製代碼
  • name

    當前狀態的名字,能夠有多個名字,用逗號隔開,如:'active,clicked'
    這個name還能夠用 void*表示: void表明動畫執行前組件的狀態; *表明動畫執行後組件的狀態,即組件的默認狀態。github

  • styles

    處於這個狀態時的樣式,如style({width: 0})api

  • options : 可選項。

transition:狀態之間轉換處理函數

function transition(
            stateChangeExpr: string, 
            steps: AnimationMetadata | AnimationMetadata[], 
            options: AnimationOptions | null = null
         ):AnimationTransitionMetadata;
複製代碼
  • stateChangeExpr

    A=>B,狀態轉換表達式,即從哪一個狀態切換到哪一個狀態。支持如下寫法:數組

    1. 狀態改變時啓動動畫
    transition("void => *", animate(500))
    複製代碼
    1. 能夠在兩個狀態變化上運行相同動畫
    transition("void <=> *", animate(500)),
    複製代碼
    1. 也能夠定義幾對狀態切換執行同一動畫
    transition("on => off, off => void", animate(500)),
    複製代碼
  • steps

    animate(),動畫執行步驟,即幾秒執行完,執行曲線是怎樣的。 如animate('100ms ease-in') 或是一個數組 [animate('100ms ease-in'),animate(600)]bash

  • options

    能夠傳入動畫的延遲值和動畫輸入參數,以更改計時數據和樣式。詳見 AnimationOptions函數。函數

用法

其實狀態 transition("void => *", animate(500))表示的是進入,在這裏能夠用 :enter 表示:動畫

transition(":enter", animate(500))
複製代碼

同理 transition(" *=> void", animate(500))離開能夠這樣寫:

transition(":leave", animate(500)) 
複製代碼

animate : 動畫

function animate(
            timings: string | number,
            styles: AnimationStyleMetadata | AnimationKeyframesSequenceMetadata |null = null
          ): AnimationAnimateMetadata;
複製代碼
  • timings : duration delay easing
    它是一個字符串,有三個參數:
    • duration : 動畫持續時間
    • delay : 動畫延遲幾秒後開始
    • easing : 動畫的緩和程度
      若是隻有一個數字,那麼會被認爲是 duration 的值。如:
    animate("200 ease-in", ...)
    // 被編譯成  duration=200, easing=ease-out
    
    animate("200 1000 ease-in", ...)
    // 被編譯成  duration=200, delay=1000, easing=ease-out
    複製代碼
  • styles
    它能夠是 style(樣式) 或 keyframes(關鍵幀),具體用法看下面詳細介紹。
    animate(timings, style({ background: "red" }))
    animate(timings, keyframes([
      style({ background: "blue", offset: 0.2})),  // 20%
      style({ background: "red", offset: 1}))   // 100%
    ])
    複製代碼

style : 樣式設置

function style(
            tokens: '*' |
            {[key: string]: string | number} |
            Array<'*'|{[key: string]: string | number}>
         ): AnimationStyleMetadata;
複製代碼

style聲明一個包含CSS屬性/樣式的鍵值對。

style({ width: 100, height: 0 })
複製代碼

Auto-styles(自適應樣式): style值能夠用 '*' 來表示,自動達到其本來的樣式,舉個例子你就明白做用了:

若是一個div它實際寬度是100px,高度爲100px,讓它高度從0 到100px變化

<div class='demo'></div>
...
.demo{
    width: 100px;
    height: 100px;
}
複製代碼

這時候用 '*'來寫

animations: [trigger(
      'autoHeight',
      [
        state('void', style({height: '0px'})),
        state('*', style({height: '*'})),
        transition('void => *',  animate(500))
      ])],

複製代碼

它就會在 500ms內 高度從 0 搭配100px。咦,彷佛沒感受到什麼做用...
在高度爲動態獲取的值時候就看到其強大了:data爲動態獲取的{ height: xxx }

<div class='demo' [ngStyle]="{'height':data.height}">
</div>
...
.demo{
    width: 100px;
}

複製代碼
animations: [trigger(
      'autoHeight',
      [
        state('void', style({height: '0px'})),
        state('*', style({height: '*'})),
        transition('void => *',  animate(500))
      ])],

複製代碼

這樣在 500ms 高度自動到達設定的值。

keyframes:關鍵幀

function keyframes(
             steps: AnimationStyleMetadata[]
         ): AnimationKeyframesSequenceMetadata;
複製代碼

它的參數是一個style()的數組,表示步驟。

animate("5s", keyframes([
  style({ backgroundColor: "red", offset: 0 }),  // 0%
  style({ backgroundColor: "blue", offset: 0.2 }), // 20%
  style({ backgroundColor: "orange", offset: 0.3 }), // 30%
  style({ backgroundColor: "black", offset: 1 })   // 100%
]))
複製代碼

這裏的 offset 和css3 keyframes裏面的百分比同樣,是時間的偏移量。
offset: 0.2表示動畫在 20%的時候的樣式。

此外,若是沒有設置偏移量,那麼偏移量將自動計算

animate("5s", keyframes([
  style({ backgroundColor: "red" }) // offset = 0
  style({ backgroundColor: "blue" }) // offset = 0.33
  style({ backgroundColor: "orange" }) // offset = 0.66
  style({ backgroundColor: "black" }) // offset = 1
]))
複製代碼

query: 選取元素,並添加動畫

function query(
            selector: string, 
            animation: AnimationMetadata | AnimationMetadata[], 
            options: AnimationQueryOptions | null = null
         ): AnimationQueryMetadata;
複製代碼
  • selector : 要選取的元素,選取方式和原生的同樣。
  • animation : 要進行的動畫序列,一個或多個。
做用:

在處於動畫序列的元素內部查找一個或多個元素,這些元素也會被加入當前動畫序列中,不過通常會從新寫一個數組來從新定義選取元素的動畫序列。

用法:

1) 選取元素並能夠限制數量
query()函數源碼中使用了element.querySelectorAll所以他能夠選取多個元素,因此咱們在選取元素的時候能夠加上一個 limit 來限制選取的數量。

// 在class爲 demo的div裏找一個div,找到的是 demo1,若是 limit爲2 的話找到的是 [demo1, demo2]。
template: `
  <div [@queryDemo] class='demo'>
    <div class='demo1'></div>
    <div class='demo2'></div>
  </div>
`,
animations: [
   trigger('queryDemo', [
     transition('void => *', [
          query( 'div', animate(...), {limit: 1} )
     ])
   ]
]
複製代碼

2) 報錯功能
默認狀況下若是選取的元素找不到則 query()函數會報錯,設置optional選項爲 true 則或忽略錯誤。

query('.demo-not-be-there', [
  animate(...),
  animate(...)
], { optional: true })
複製代碼
選擇器的特殊值

query()函數裏面用僞選擇器能夠選出特定的元素:

  • query(":enter")/query(":leave") : 選取新插入 / 移除的元素
  • query(":animating") : 選取全部正在進行動畫的元素
  • query("@triggerName") : 選取有特定觸發器的元素
  • query("@*") : 選取全部具備觸發器的元素
  • query(":self") : 把當前元素增長到動畫序列中

多個僞選擇器能夠合在一塊兒組成選擇器查詢字符串:

query(':self, .record:enter, .record:leave, @subTrigger', [...])
複製代碼
例子
@Component({
  selector: 'inner',
  template: `
    <div [@queryAnimation]="exp">
      <h1>Title</h1>
      <div class="content">
        Blah blah blah
      </div>
    </div>
  `,
  animations: [
   trigger('queryAnimation', [
     transition('* => goAnimate', [
       // 隱藏裏面的元素
       query('h1', style({ opacity: 0 })),
       query('.content', style({ opacity: 0 })),
 
       // 一個一個地執行裏面元素的動畫
       query('h1', animate(1000, style({ opacity: 1 })),
       query('.content', animate(1000, style({ opacity: 1 })),
     ])
   ])
 ]
})
class Cmp {
  exp = '';
 
  goAnimate() {
    this.exp = 'goAnimate';
  }
}
複製代碼

sequence : 序列

function sequence(
            steps: AnimationMetadata[], 
            options: AnimationOptions | null = null
         ): AnimationSequenceMetadata;
複製代碼
  • steps : 動畫序列的步驟

它能夠由樣式或動畫函數調用組成。對style()的調用將當即應用提供的樣式數據,而對animate()的調用將在它延遲時間後應用它的樣式數據。

  • options: 參見 AnimationOptions
// 這是一個動畫序列
sequence([
  style({ opacity: 0 })),
  animate("1s", { opacity: 1 }))
])
複製代碼
那到底什麼是序列呢?

它是一個動畫列表[A,B,C],裏面的動畫挨個執行:執行完A再執行B,B執行完再執行C。 它能夠應用在 grouptransition裏面,它只會在每一個內部動畫步驟完成後再繼續執行下一條指令。

將一個數組做爲動畫數據傳遞到transition時,默認使用序列。以下面的[animate(500, style({...})), animate(500)]就是序列。

animations: [trigger(
      'demo',
      [
        state('void', style({...})),
        state('*', style({...})),
        transition(
            'void => *', [animate(500, style({...})), animate(500)])
      ])],
複製代碼
它和組(group)的異同:

都是動畫列表,序列是一個一個執行,組是並行執行。

group : 組

function group(
            steps: AnimationMetadata[],
            options: AnimationOptions | null = null
         ): AnimationGroupMetadata;
複製代碼
  • steps : 動畫步驟數據
    它能夠由樣式或動畫函數調用組成。在一個組中,每一個樣式或動畫函數的調用都會當即同時執行,固然你可使用關鍵幀或者動畫的延遲函數來延遲執行動畫。
  • options: 參見 AnimationOptions
group([
  animate("1s", { background: "black" }))
  animate("2s", { color: "white" }))
])
複製代碼
什麼是組呢?

組是一個並行運行的動畫步驟列表。當存在不少樣式在不一樣時間段開始或結束動畫,咱們須要對它統一進行管理的時候做用很是明顯。利用組咱們能夠輕易控制它們同時開始動畫或者同時結束動畫。
group函數既能夠在序列(sequence)中使用,也能夠在轉換(transition)中使用,它只會在全部內部動畫步驟完成後繼續執行下一條指令。

group官網介紹

AnimationOptions :動畫的可選項

import { AnimationOptions } from '@angular/animations';
複製代碼
interface AnimationOptions { 
  delay?: number|string
  params?: {[name: string]: any}
}
複製代碼
  • delay: number|string
    動畫的延遲值。
  • params
    在啓動動畫時傳入參數,以更改樣式。
如下動畫函數可配置 AnimationOptions:
  • transition()
  • sequence()
  • group()
  • query()
  • animation()
  • useAnimation()
  • animateChild()
  • 使用AnimationBuilder服務構建的動畫
子接口
  • AnimateChildOptions
  • AnimationQueryOptions

實例: 好比如今想作一個動畫效果 : 點擊按鈕 div 寬從 0 到100px。

  1. 添加動畫觸發器
// ts
import { trigger } from '@angular/core';

@Component({
  templateUrl: 'my-demo.html',
  animations: [
    trigger( 'growWidth', [ // 這裏是定義的一些動畫效果] )
  ]
})

// html
<div [@growWidth]>...</div>
複製代碼
  1. 再進行狀態(寬度)的改變
import { trigger, state, style } from '@angular/core';

@Component({
  templateUrl: 'my-demo.html',
  animations: [
    trigger( 'growWidth', [ 
         state( 'smWidth, void', style({width: '0px'}) ),
         state( 'lgWidth', style({width: '100px'}) )
    ] )
  ]
})

複製代碼

上面定義了兩個狀態,一個是寬度最小時候爲0,一個寬度最大時候爲 100px; 那麼有growWidth 動畫觸發器的 div 會完成這個寬度 0 到100px的動畫。

  1. 上面雖然完成了兩個不一樣狀態之間的改變,可是沒有過渡效果,用transition實現過渡。
import { trigger, state, transition, animate } from '@angular/core';

@Component({
  templateUrl: 'my-demo.html',
  animations: [
    trigger( 'growWidth', [ 
         state( 'smWidth, void', style({width: '0px'}) ),
         state( 'lgWidth', style({width: '100px'}) ),
         transition('smWidth => lgWidth', animate(600)),
         transition('lgWidth => smWidth', animate(600)),
    ] )
  ]
})

複製代碼

上面規定了從 smWidth 狀態到 lgWidth狀態須要0.6s的時間,因此能夠看到div的寬度是慢慢變大的。

| 更多API用法更新於 github

相關文章
相關標籤/搜索