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

相关文章
相关标签/搜索