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
還分別匹配和的表達式值1
(0
但不匹配,和其他真假值)
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', ...}),
其實這個作用是爲了本盒子計算出當前盒子的高度, 從而實現收起動畫的過渡