Angular(2+)动画API用法详解

动画相关的 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

    当前状态的名字,可以有多个名字,用逗号隔开,如:'active,clicked'
    这个name还可以用 void*表示: void代表动画执行前组件的状态; *代表动画执行后组件的状态,即组件的默认状态。

  • styles

    处于这个状态时的样式,如style({width: 0})

  • 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)]

  • 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值