动画相关的 API 都是在 @angular/animations
里面引入的。
import { 你想要的API } from '@angular/animations';复制代码
trigger : 由它触发动画效果,称动画触发器。
function trigger( name: string, definitions: AnimationMetadata[] ):AnimationTriggerMetadata;复制代码
-
name
动画触发器名字, 如
growWidth
-
definitions
要执行的动画, 如
[ transition("void => *", [style({opacity: 0}), animate(600, style({ opacity: 1}))] )],
state :定义目标处于某一状态时的样式
function state( name: string, styles: AnimationStyleMetadata, options?: {params: {[name: string]: any}} ):AnimationStateMetadata;复制代码
-
name
当前状态的名字,可以有多个名字,用逗号隔开,如:
这个name还可以用'active,clicked'
。void
和*
表示:void
代表动画执行前组件的状态;*
代表动画执行后组件的状态,即组件的默认状态。 -
styles
处于这个状态时的样式,如
style({width: 0})
-
options : 可选项。
transition:状态之间转换处理函数
function transition( stateChangeExpr: string, steps: AnimationMetadata | AnimationMetadata[], options: AnimationOptions | null = null ):AnimationTransitionMetadata;复制代码
-
stateChangeExpr
A=>B,状态转换表达式,即从哪个状态切换到哪个状态。支持以下写法:
- 状态改变时启动动画
transition("void => *", animate(500))复制代码
- 可以在两个状态变化上运行相同动画
transition("void <=> *", animate(500)),复制代码
- 也可以定义几对状态切换执行同一动画
transition("on => off, off => void", animate(500)),复制代码
-
steps
animate(),动画执行步骤,即几秒执行完,执行曲线是怎样的。 如
animate('100ms ease-in')
或是一个数组[animate('100ms ease-in'),animate(600)]
-
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-outanimate("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变化
....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 }....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: ``,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: ``, 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'; }}复制代码Title
Blah blah blah
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。 它可以应用在 group
和transition
里面,它只会在每个内部动画步骤完成后再继续执行下一条指令。
将一个数组作为动画数据传递到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
)中使用,它只会在所有内部动画步骤完成后继续执行下一条指令。 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。
- 添加动画触发器
// tsimport { trigger } from '@angular/core';@Component({ templateUrl: 'my-demo.html', animations: [ trigger( 'growWidth', [ // 这里是定义的一些动画效果] ) ]})// html...复制代码
- 再进行状态(宽度)的改变
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的动画。
- 上面虽然完成了两个不同状态之间的改变,但是没有过渡效果,用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用法更新于