Angular Animation简单来说 就是状态和状态之间的转场效果。每一种状态对应一种样式(style)。Angular Animation指导从一种状态的样式过渡到另一种状态的样式效果过程。
Angular Animation和咱们Android里面的属性动画类似。
如果想在我们的应用中使用动画,有一个前提条件,得先引入BrowserAnimationsModule模块。建议在app module里面引入。
开始部分,我们先贴出文章里面涉及到的所有例子的下载的地址:https://github.com/tuacy/AngularAnimation
例子都是非常简单的例子,咱也是个初学者。高深的例子咱也写不出来。
一、Angular Animation里面各个函数解释
Angular Animation动画使用起来不难,在加上咱之前有Android动画的经验。Angular Animation看起来就更加的简单了。
1.1. trigger触发器
trigger触发器,trigger
将根据提供的triggerName
值创建一个动画触发器。在模板中使用[@triggerName]语法来把它附加到一个或多个元素上去。可以简单的理解为这个时候就把元素和触发器对应的动画绑定起来了。
比如如下的代码我们就定义了一个名字为flyInOut的一个触发器。
import {Component, OnInit} from '@angular/core';
import {animate, keyframes, state, style, transition, trigger} from '@angular/animations';
@Component({
selector: 'app-keyframes-animation',
templateUrl: './keyframes-animation.component.html',
styleUrls: ['./keyframes-animation.component.css'],
animations: [
trigger('flyInOut', [
state('in', style({transform: 'translateX(0)'})),
// keyframes多阶段动画(任何状态切换的时候都使用该动画)
transition('* => *', [
animate(1000, keyframes([
style({opacity: 0, transform: 'translateX(-100%)', offset: 0}),
// 多往右边移除一点
style({opacity: 1, transform: 'translateX(50%)', offset: 0.5}),
style({opacity: 1, transform: 'translateX(0)', offset: 1.0})
]))
])
])
]
})
export class KeyframesAnimationComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}
上面的代码只是定义了一个触发器,但是还没有把触发器和页面上的元素绑定起来(在模板中使用[@triggerName]来绑定),比如如下的代码我们就把div绑定到了这个触发器上。
<br>
<h5>keyframes关键帧多阶段动画</h5>
<br>
<div style="width: 200px; height: 200px;background-color: #67ee38" [@flyInOut]></div>
<br>
1.2. state状态
state状态,通过这个state函数来定义每个状态最终的样式(动画开始时候的样子和动画结束之后的样子);想要动画动起来需要通过改变状态(state)来触发(trigger)动画(animate)。
上面咱们贴了trigger触发器时候的代码实例,在trigger函数里面有state函数,定义了一个 in的状态对应的样式为transform: 'translateX(0)'。
1.3. transition转换
transition负责定义各种 state之间的转换关系,并且定义state转换的时候使用什么的样的动画来完成。
这里我们着重要讲下状态装换在Angular Animation中是怎么定义的状态之间装换的。
trigger('animationState', [
// stateA 状态最终样式
state('stateA', style({
backgroundColor: '#67ee38',
transform: 'scale(1)'
})),
// stateB 状态最终样式
state('stateB', style({
backgroundColor: '#4a302c',
transform: 'scale(1.1)'
})),
// stateA 到 stateB 状态动画
transition('stateA => stateB', animate('500ms ease-in')),
// stateB 到 stateA 状态动画
transition('stateB => stateA', animate('500ms ease-out'))
]),
上面的代码trigger里面有两个transition。分别定义了'stateA => stateB'和'stateB => stateA'的状态变化。Angular Animation里面两个状态之间的装换就是通过 '状态 => 状态' 这样的表达式来定义的。在Angular Animation里面有两种特殊的状态; ×、void状态。其中×状态匹配任何状态,void状态表示元素没有被附加到视图时候的状态。
讲到状态,那咱们还得提下元素的入场和出场动画的添加了。比如下面的实例。我们定义了入场和出场的动画。
animations: [
trigger('flyInOut', [
state('in', style({opacity: 1, transform: 'translateX(0) scale(1)'})),
// 进场动画
transition('void => *', [
style({opacity: 0, transform: 'translateX(-100%) scale(0)'}),
animate(500)
]),
// 出场动画
transition('* => void', [
animate(500, style({opacity: 0, transform: 'translateX(100%) scale(0)'}))
])
])
]
应该比较好理解吧,void => * 表示入场。* => void 表示出场。当然入场你也可以用:enter代替,出场可以用:leave代替。
1.4. style样式
Angular Animation动画的过程就是在改变元素的CSS样式或者CSS3 transform 属性。style函数可以出现在state函数,transition函数,animate函数中。
假设有这样的需求,动画结束但是我们不想保留动画结束点的那个状态。实现过程查看如下代码。
// 动画结束不保留状态
trigger('animationStateNoSave', [
transition('stateA => stateB', [
style({
backgroundColor: '#4a302c',
transform: 'scale(1.1)'
}),
animate('1000ms ease-in', style({
backgroundColor: '#67ee38',
transform: 'scale(1)'
}))
]),
transition('stateB => stateA', [
style({
backgroundColor: '#67ee38',
transform: 'scale(1)'
}),
animate('1000ms ease-in', style({
backgroundColor: '#4a302c',
transform: 'scale(1.1)'
}))
])
])
注意这里我们没有通过state函数来指定状态对应的style。
Angular Animation支持的CSS样式如下:
css属性的名字 | animation style 对应名字 | 解释 |
---|---|---|
background-color | backgroundColor | 设置元素的背景颜色 |
background-position | backgroundPosition | 设置背景图像的起始位置 |
border-bottom-color | borderBottomColor | 设置下边框的颜色 |
border-bottom-width | borderBottomWidth | 设置下边框的宽度 |
border-left-color | borderLeftColor | 属性设置元素的左边框的颜色 |
border-left-width | borderLeftWidth | 属性设置元素的左边框的宽度 |
border-right-color | borderRightColor | 属性设置元素的右边框的颜色 |
border-right-width | borderRightWidth | 属性设置元素的右边框的宽度 |
border-spacing | borderSpacing | 设置相邻单元格的边框间的距离 |
border-top-color | borderTopColor | 属性设置元素的上边框的颜色 |
border-top-width | borderTopWidth | 属性设置元素的上边框的宽度 |
bottom | bottom | 定元素的底部边缘 |
clip | clip | 剪裁绝对定位元素 |
color | color | 规定文本的颜色 |
font-size | fontSize | 设置字体的尺寸 |
font-weight | fontWeight | 设置文本的粗细 |
height | height | 设置元素的高度 |
left | left | 设置元素的左边缘 |
letter-spacing | letterSpacing | 设置字符间的空白(字符间距) |
line-height | lineHeight | 设置行间的距离(行高) |
margin-bottom | marginBottom | 设置元素的下外边距 |
margin-left | marginLeft | 设置元素的左外边距 |
margin-right | marginRight | 设置元素的右外边距 |
margin-top | marginTop | 设置元素的上外边距 |
max-height | maxHeight | 设置元素的最大高度 |
max-width | maxWidth | 设置元素的最大宽度 |
min-height | minWidth | 设置元素的最小高度 |
min-width | minWidth | 设置元素的最小宽度 |
opacity | opacity | 设置元素的不透明级别 |
outline-color | outlineColor | 设置元素整个轮廓的颜色 |
outline-width | outlineWidth | 设置元素整个轮廓的宽度 |
padding-bottom | paddingBottom | 设置元素的下内边距 |
padding-left | paddingLeft | 设置元素的左内边距 |
padding-right | paddingRight | 设置元素的右内边距 |
padding-top | paddingTop | 设置元素的上内边距 |
right | right | 规定元素的右边缘 |
text-indent | textIndent | 首行文本的缩进 |
text-shadow | textShadow | 向文本设置阴影 |
top | top | 规定元素的顶部边缘 |
visibility | visibility | 规定元素是否可见 |
width | width | 元素的宽度 |
word-spacing | wordSpacing | 设置单词间的空白 |
z-index | zIndex | 设置元素的堆叠顺序 |
Angular Animation支持的CSS3
transform 属性如下:
transform 属性 | 描述 |
---|---|
matrix(n,n,n,n,n,n) | 2D 转换,使用六个值的矩阵 |
matrix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n) | 3D 转换,使用 16 个值的 4x4 矩 |
translate(x,y) | 2D 转换 |
translate3d(x,y,z) | 3D 转换。 |
translateX(x) | 转换,只是用X轴 |
translateY(y) | 转换,只是用 Y 轴的值 |
translateZ(z) | 3D 转换,只是用 Z 轴的值。 |
scale(x,y) | 缩放转换 |
scale3d(x,y,z) | 3D 缩放转换。 |
scaleX(x) | 通过设置 X 轴的值来定义缩放转换 |
scaleY(y) | 通过设置 Y 轴的值来定义缩放转换 |
scaleZ(z) | 通过设置 Z 轴的值来定义 3D 缩放转换。 |
rotate(angle) | 2D 旋转,在参数中规定角度 |
rotate3d(x,y,z,angle) | 3D 旋转。 |
rotateX(angle) | 沿着 X 轴的 3D 旋转 |
rotateY(angle) | 沿着 Y 轴的 3D 旋转 |
rotateZ(angle) | 沿着 Z 轴的 3D 旋转 |
skew(x-angle,y-angle) | 沿着 X 和 Y 轴的 2D 倾斜转换 |
skewX(angle) | 沿着 X 轴的 2D 倾斜转换 |
skewY(angle) | 沿着 Y 轴的 2D 倾斜转换 |
perspective(n) | 3D 转换元素定义透视视图 |
1.5. animate动画
animate表示具体的动画定义
。定义动画的持续时间,动画延时多长时间执行,动画的缓动函数(https://easings.net/zh-cn)。
1.6. group组
group
是一个动画特定的函数,指定一个并行运行的动画步骤列表。分组动画是当一系列样式必须在不同的开始/结束时间进行动画/关闭时很有用。同时执行多个动画。(多个动画组合在一起同时触发)。比如如下效果图,同时有颜色变化动画和翻转动画执行。
1.7. keyframes关键帧
keyframes描述每个样式条目是如何应用的,以及在什么点动画弧(很像CSS关键帧动画)。相当于把动画分段了。比如如下动画我们通过keyframes实现了动画多往左边移动了一段距离在回到最终位置(当然了你也可以通过缓动函数来实现)。
1.8. sequence顺序
sequence指定逐个运行的动画步骤列表,这个也就是和group特性正好相反,一个同时进行,一个按先后顺序一个一个的进行。
比如下面的例子,进场动画我们就定义了几个动画顺序执行
import {Component, OnInit} from '@angular/core';
import {animate, sequence, state, style, transition, trigger} from '@angular/animations';
@Component({
selector: 'app-sequence-animation',
templateUrl: './sequence-animation.component.html',
styleUrls: ['./sequence-animation.component.css'],
animations: [
trigger('flyInOut', [
state('in', style({transform: 'rotateX(0) translateX(0)', opacity: 1})),
// 多个动画同时执行
transition('void => *', sequence([
style({
opacity: 0,
}),
animate('1s ease-in-out', style({
opacity: 1,
}
)),
animate('1s ease-in-out', style({
transform: 'rotateX(90deg)',
}
)),
animate('2s ease', style({
transform: 'rotateY(90deg)',
})),
]))
])
]
})
export class SequenceAnimationComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}
1.10. query
query用于在当前元素中查找(query)一个或多个内部元素在序列中进行动画。把动画作用在子元素上。
import {Component, OnInit} from '@angular/core';
import {animate, query, style, transition, trigger} from '@angular/animations';
@Component({
selector: 'app-query-animation',
templateUrl: './query-animation.component.html',
styleUrls: ['./query-animation.component.css'],
animations: [
trigger('queryAnimation', [
// 入场的时候对子元素采用动画
transition('* => goAnimate', [
// hide the inner elements
query('h1', style({
opacity: 0
})),
query('.content', style({
opacity: 0
})),
// 动画作用于内容元素
query('h1', animate(1000, style({
opacity: 1
}))),
query('.content', animate(1000, style({
opacity: 1
})))
])
])
]
})
export class QueryAnimationComponent {
}
1.11. stagger
stagger需要在query里面使用,stagger的作用在于每个动画发出之后隔多长时间在发下一个动画。比如咱们有这样的需求,ul里面有好多个li。想要一个这样的效果。li的动画一个挨着一个执行。代码如下
trigger('listAnimation', [
transition('* => *', [ // each time the binding value changes
query(':enter', [
// 所有子元素入场动画
style({opacity: 0}),
stagger('0.5s', [
animate('0.5s', style({opacity: 1}))
])
])
])
])]
1.12. animateChild
在angular中,因为每次动画被触发,父动画将始终获得优先权,任何子动画都将被阻止,为了子动画也有动画效果,父动画必须查询每一个包含子动画的元素并用animateChild来运行子动画。animateChild需要和query一起使用。
trigger('parentAnimation', [
transition('false => true', [
// 查找parentAnimation对应element里面的header标签执行动画
query('header', [
style({opacity: 0}),
animate(500, style({opacity: 1}))
]),
query('@childAnimation', [
animateChild()
])
])
]),
trigger('childAnimation', [
transition('false => true', [
style({opacity: 0}),
animate(500, style({opacity: 1}))
])
])
1.13. 动画回调
动画开始的时候有个回调函数,动画结束的时候也有个回调函数。
1.9. animation的封装
借助useAnimation函数我们可以对动画做一个简单的封装。比如如下的代码我们把封装了两个动画,放在animation.ts文件里面。
import {animate, animation, style, transition, trigger, useAnimation} from '@angular/animations';
// 封装动画1
const inAnimation = animation([
style({
opacity: '{{ start }}',
transform: 'translateX(-100%)'
}),
animate('{{ time }}',
style({
opacity: '{{ end }}',
transform: 'translateX(0)'
}))
], {params: {time: '1000ms', start: 0, end: 1}});
// 封装动画2
const outAnimation = animation([
style({
opacity: '{{ start }}',
transform: 'translateX(0)'
}),
animate('{{ time }}',
style({
opacity: '{{ end }}',
transform: 'translateX(-100%)'
}))
], {params: {time: '1000ms', start: 0, end: 1}});
// 如下面我定一个动效用到上面封装的动画
export const routerEnterLeave = trigger('fadel', [
// 入场
transition(':enter', [
useAnimation(inAnimation, {
params: {
time: '2s',
start: 0,
end: 1
}
})
]),
// 出场
transition(':leave', [
useAnimation(outAnimation, {
params: {
time: '2s',
start: 1,
end: 0
}
})
])
]);
关于Angular Animation咱们就撤这么多,文章中涉及到的所有例子下载地址https://github.com/tuacy/AngularAnimation。希望能帮到大家。最后还是想强调下最好的文档是官方文档https://v6.angular.live/guide/animations。