import { Component, Input, OnInit } from '@angular/core'; import { trigger, state, style, animate, transition, group, sequence, keyframes, useAnimation, stagger, animateChild, query, animation } from '@angular/animations'; var fadeAnimation = animation([ style({ opacity: '{{ start }}' }), animate('{{ time }}', style({ opacity: '{{ end }}' })) ], { params: { time: '1000ms', start: 0, end: 1 } }); @Component({ selector: 'app-animate', templateUrl: './animate.component.html', styleUrls: ['./animate.component.css'], animations: [ trigger('state', [ state('pointA', style({ left: '0%' })), transition('pointA => pointB', [ style({ border: "3px solid #000" }), animate(1000, style({ left: "100%" })), group([ //basic animation ]), sequence([ //basic animation ]), query(":leave", [ //basic animation ]), query(":leave", stagger(1000, [ //basic animation ])), useAnimation(fadeAnimation, { params: { time: '2s', start: 1, end: 0 } }) ]) ]) ] }) export class AnimateComponent implements OnInit { state = 'pointA'; constructor() { } ngOnInit() { } }
源码链接:https://github.com/angular/angular/blob/master/packages/animations/src/animation_metadata.ts
在开始前,我们先不管如何写动画,先看trigger是什么,所有的trigger都可以直接绑定element
<div [@state]="state1" ></div>
像这样,只要state1 有改变,trigger都会触发。
在trigger世界里,是能控制state 和 transition。
state是转场的“场”
state("void", style({ height: 0 })) //void是保留字,是没有东西 state("*", style({ height: 0 })) //*是保留字,是default state("closed", style({ height: 0 })) state("open, visible", style({ height: "*" }))
transition是转场,state去到下一个state
transition("on => off", animate(500)), transition("on <=> off", animate(500)), transition("on => off, off => void", animate(500)), transition("void => *", animate(500)), transition("* => *", animate("1s 0s")), transition((fromState, toState) => { return fromState == "off" && toState == "on"; }, animate("1s 0s")) transition(":enter", animate(500)), transition(":leave", animate(500)),
当了解state 和 transition 后,我们需要了解基础动画 style 和 animate
style 使用方式和css一样,这里就不多说
animate 使用方式就很多 (可以控制过渡时长,延迟,和过渡动作,结束动画)
animate(500, style(...)) animate("1s", style(...)) animate("100ms 0.5s", style(...)) animate("5s ease", style(...)) animate("5s 10ms cubic-bezier(.17,.67,.88,.1)", style(...)) animate(500, style({ background: "red" })) animate(500, keyframes([ style({ background: "blue" })), style({ background: "red" })) ])
animate 对象里可以有style 和 keyframe,懂css的都明白。
动画基础讲述的是style 和 animate, 高级动画是group, sequence, query,stagger。所有的高级都基于动画基础的组装。
group是把多个基础给包在一起,同时触发
group([ animate("1s", { background: "black" })) animate("2s", { color: "white" })) ])
sequence就相对的,是一个一个触发。(默认功能)
sequence([ style({ opacity: 0 })), animate("1s", { opacity: 1 })) ])
如果你不要特地包一个sequence,你可以直接写基础动画,效果是一样的
query是可以寻找指定的子层进行动画,寻找的方式有
query('div', [ animate(...), animate(...) ], { limit: 1 }) query('.some-element-that-may-not-be-there', [ animate(...), animate(...) ], { optional: true }) query(':self, .record:enter, .record:leave, @subTrigger', [...]) - Querying for newly inserted/removed elements using `query(":enter")`/`query(":leave")` - Querying all currently animating elements using `query(":animating")` - Querying elements that contain an animation trigger using `query("@triggerName")` - Querying all elements that contain an animation triggers using `query("@*")` - Including the current element into the animation sequence using `query(":self")`
limit 是声明限制element的数量, optional 是如果query可能没有找到,就得声明
:enter / :leave 等等都是特别的表达寻找式,这里不多说
stagger 是间隔,通常用在ngFor,场景是当你需要删除多个元素时,你需要每一个元素都是间隔离开,而不是同时离开
query(':leave', [ stagger(100, [ animate('0.5s', style({ opacity: 0 })) ]) ]), query(':enter', [ style({ opacity: 0 }), stagger(100, [ animate('0.5s', style({ opacity: 1 })) ]) ])
调用query才能使用stagger,因为query才可以选着多个元素
animateChild() 这里有bug,在不调用这功能时,子层的trigger是不会触发的,但是目前就是会触发……
query('@childAnimation', animateChild() ))
query('@childAnimation', stagger(100, [ animateChild() ]))
UseAnimate是一个调用方法,也是复用的部分
var fadeAnimation = animation([ style({ opacity: '{{ start }}' }), animate('{{ time }}', style({ opacity: '{{ end }}')) ], { params: { time: '1000ms', start: 0, end: 1 }}); useAnimation(fadeAnimation, { params: { time: '2s', start: 1, end: 0 } })
最后就是所有的基础动画都是可以组装的,即使我没有给出所有的例子。在组装一定是在array里 [],只要是逻辑就能装的,transition的例子就是这样。