angular動畫(一)

https://williamjuan027.github.io/angular-animations-explorer/home

注入模塊

BrowserAnimationsModule

來個小案例

@Component({
  ...
  animations: [
    trigger('enabledStateChange', [
      state('default', style({opacity: 1})),
      state('disabled', style({opacity: .5, background: '#000'})),
      transition('* => *', animate('1500ms ease-out'))
    ]),
  ]
})

  stateOfElement = 'default';
  toggleMethod() {
    this.stateOfElement = this.stateOfElement === 'default' ? 'disabled' : "default"
  }
<div [@enabledStateChange]="stateOfElement"></div>
<button (click)="toggleMethod()">Click</button>

trigger

trigger(name: string, definitions: AnimationMetadata[]): AnimationTriggerMetadata
參數
name string 一個標識字符串。
definitions AnimationMetadata[] 一個動畫定義對象,包含一個數組 state()transition()聲明。

創建一個命名的動畫觸發器

禁用動畫

當爲 true 時,特殊的動畫控件綁定@.disabled綁定會阻止所有動畫的渲染。將 @.disabled綁定放在元素上以禁用元素本身的動畫,以及元素內的任何內部動畫觸發器。

@Component({
  selector: 'my-component',
  template: `
    <div [@.disabled]="isDisabled">
      <div [@childAnimation]="exp"></div>
    </div>
  `,
  animations: [
    trigger("childAnimation", [
      // ...
    ])
  ]
})
class MyComponent {
  isDisabled = true;
  exp = '...';
}

另一種方式禁用

 @HostBinding('@.disabled')
  public animationsDisabled = true;

如果 DOM 的某個區域(或整個應用程序)禁用了動畫,動畫觸發器回調仍會觸發,但持續時間爲零。

state()

附加到元素的觸發器中聲明動畫狀態。

      state('default', style({opacity: 1})),

transition()

滿足特定指定條件時播放的動畫過渡。

  • 第一個參數: 變化表達式
fromState => toState,這表示應該發生轉換的動畫(a=>b)

transition('open => closed', animate('.5s ease-out', style({ height: 0 }) ))

fromState <=> toState,這表示應該發生轉換的動畫,(a<=>b)

transition('enabled <=> disabled', animate('1s cubic-bezier(0.8,0.3,0,1)'))
  • :enter/ :leave 當元素顯示/隱藏DOM時,出現過渡動畫, 產生過渡動畫(*ngIf)
  transition(':enter', [
        style({ opacity: 0 , background: '#e53131'}),
        animate('1500ms', style({ opacity: 1, background: '#6b6cc5' }))
      ])

 transition(':leave', [
        style({ opacity: 0 , background: '#e53131'}),
              animate('1500ms', style({opacity: 1, background: '#6b6cc5'}))
      ])
<div [@enabledStateChange]="num" *ngIf="bool">
    內容
</div>
  • :increment/ :decrement,表示當綁定到觸發器元素的數值表達式的值增加或減少時,應該發生過渡動畫
 transition(':increment', animate('1s ease', keyframes([
        style({ transform: 'scale(1)', offset: 0}),
        style({ transform: 'scale(1.1)', offset: 0.7}),
        style({ transform: 'scale(1)', offset: 1})
      ]))),
      transition(':decrement', animate('1s ease', keyframes([
        style({ transform: 'scale(1)', offset: 0}),
        style({ transform: 'scale(1.1)', offset: 0.7}),
        style({ transform: 'scale(1)', offset: 1})
      ]))),
<div [@enabledStateChange]="num">
    內容
</div>

++num
--num
  • 用逗號分割,來表達多個條件

    transition(':increment, * => enabled, :enter', 
             ... )
    
  • void 元素的缺失

    * 匹配任意狀態

    void => * 等價於 :enter dom顯示

    * => void 等價於 :leave dom刪除

    true並且false還分別匹配和的表達式值10但不匹配,和其他真假值)

query

在序列中動畫的當前元素中查找一個或多個內部元素。與 一起使用animate()

query(selector:string,animation: AnimationMetadata | AnimationMetadata[])

selector 類型 string 要查詢的元素

query(":enter") 或者 query(":leave") 查詢 顯示/刪除的元素

query(":animating") 查詢所有當前動畫元素

query("@triggerName") 查詢所有動畫元素

query("@*"):查詢所有包含動畫觸發器的元素。

query(":self"):將當前元素包含到動畫序列中。

多個條件

query(':self, .record:enter, .record:leave, @subTrigger',)

demo

  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 }))),
      ])
    ])
<div [@queryAnimation]="exp">
  <h1>Title</h1>
  <div class="content">
    Blah blah blah
  </div>
</div>
<button (click)="exp='goAnimate'">goAnimate</button>

animate

參數

  • 第一個參數

    type AnimateTimings = {
        duration: number;    持續時間
        delay: number;		延遲時間
        easing: string | null; 
    };
    
  • animate(500):持續時間爲 500 毫秒。
  • animate("1s"): 持續時間爲 1000 毫秒。
  • animate("100ms 0.5s"): 持續時間爲 100 毫秒,延遲爲 500 毫秒。
  • animate("5s ease-in"): 持續時間爲 5000 毫秒,漸進式。
  • animate("5s 10ms cubic-bezier(.17,.67,.88,.1)"): 持續時間爲 5000 毫秒,延遲爲 10 毫秒,根據貝塞爾曲線緩動。

group

動畫列表組

group([
  animate("1s", style({ background: "black" })),
  animate("2s", style({ color: "white" }))
])

參數的使用
transition(
    '1 => 0',
    [
      style({
        height: '0',
        overflow: 'hidden',
      }),
      group([
        query('@*', animateChild(), { optional: true }),
        animate(
          '{{ duration }}ms {{ delay }}ms {{ ease }}',
          style({
            overflow: 'hidden',
            height: "*",
          }),
        ),
      ]),
    ],
    { params: { duration: 150, delay: '0', ease: 'ease-out' } },
  )

摺疊動畫

import { animate,animateChild,AnimationTriggerMetadata,group,query,state,style,transition, trigger} from '@angular/animations';

/* usage: [@tdCollapse]="{ value: true | false, params: { duration: 500 }}"
 */
export const tdCollapseAnimation: AnimationTriggerMetadata = trigger('tdCollapse', [
  state('0', style({
    height: '*', overflow: '*'
  })),
  state('1', style({
    height: '0', overflow: 'hidden'
  })),
  transition('0 => 1', [
    style({overflow: 'hidden', height: '*'}),
    group([
      query('@*', animateChild(), {optional: true}),
      animate('{{duration}}ms {{delay}}ms {{ease}}', style({height: '0', overflow: 'hidden'})),
    ])
  ], {params: {duration: 150, delay: '0', ease: 'ease-in'}}),
  transition('1 => 0', [
    style({height: '0', overflow: 'hidden'}),
    group([
      query('@*', animateChild(), {optional: true}),
      animate(
        '{{duration}}ms {{delay}}ms {{ease}}',
        style({overflow: 'hidden', height: '*'})
      )
    ])
  ], {params: {duration: 150, delay: '0', ease: 'ease-out'}},)
])

html

<div [@tdCollapse]="{ value: triggerState, params: { duration: 500 }}">
  <div style="background: #c45a5a;height: 400px;"></div>
</div>
<button (click)="triggerState=!triggerState">Click</button>
@Component({
  ...
  animations: [
    tdCollapseAnimation
  ]
})

triggerState: boolean = true;

邏輯解釋

{optional:true} 是可選的意思, 就是如果傳遞參數用傳遞的參數,沒有就用默認的

就是如果[@tdCollapse]="{ value: triggerState, params: { duration: 500 }}" 傳入了,就用它的

query('@*', animateChild(), {optional: true}), 這個動畫或者子代都遵循這套規則

我們知道來個原生的例子方便我們理解,我們知道我們在使用折騰動畫需要確認一個高度, 或者使用js動畫,計算子代的高度,從而產生過渡的效果

.yl-fb-hide {
  transition: max-height .3s;
  max-height: 0;
  overflow: hidden;
}

.yl-fb-show {
  overflow: auto;
  max-height: 1000px;
  animation: hide-scroll .3s backwards;
}
@keyframes hide-scroll {
  from{
    max-height: 0;
    overflow:hidden;
  }
  to{
    max-height: 1000px;
    overflow:hidden;
  }
}
  transition('0 => 1', [
    style({overflow: 'hidden', height: '*'}),
    group([
      query('@*', animateChild(), {optional: true}),
      animate('{{duration}}ms {{delay}}ms {{ease}}', style({height: '0', overflow: 'hidden'})),
    ])
  ], {params: {duration: 150, delay: '0', ease: 'ease-in'}}),

可能我們疑惑0 => 1 中爲啥要在默認設置 style({overflow: 'hidden', ...}),

其實這個作用是爲了本盒子計算出當前盒子的高度, 從而實現收起動畫的過渡

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章