本文是自己的学习笔记,主要参考资料如下。
- Angular官方文档:https://angular.io/guide/animations
这篇文章介绍如何用Angular实现动画效果,比如划入划出,缩小变大。
先要在app.module.ts
中import
对应的包BrowserAnimationsModule
。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
这部分是一个示例,演示点击一个button
后,一个div
平滑地变大变小同时改变颜色。
在想要有动画效果的组件中引入下面与动画细节相关的组件,
这些组件与动画的具体效果有关,比如一个元素变化前的样子和变化后的样子,元素从A点移到B点花多少时间,恒速度移过去还是速度逐渐提升移过去,等等。
import {
trigger,
state,
style,
animate,
transition,
// ...
} from '@angular/animations';
关于动画的部分都是定义在@Component
注解中,我新建一个Component
来写示例代码ng g component open-close
定义一个trigger
,里面是动画的所有细节,同时我们需要为这个trigger
命名,名字必须是驼峰或者中间用破折号隔开,比如backgroundColor
或者background-Color
。
命名是需要和元素绑定,元素会通过名字知道需要执行什么动画。
可以看下面这个示例,命名了一个动画叫openClose
,动画细节代码暂时省略。
@Component({
selector: 'app-open-close',
templateUrl: './open-close.component.html',
styleUrls: ['./open-close.component.css'],
animations: [
trigger('openClose', [
// ...
]),
]
})
export class OpenCloseComponent implements OnInit {
// ···
}
很多动画都可以看成从一个状态到另一个状态,或者说从状态1到状态2再到状态3,总之最小可以拆分成两个状态的变化。
比如从A点移到B点,高度从400缩小到300,从紫色变成红色等等都属于状态变化,当然这些可以一起发生。
在本示例中,div
的高度将缩小,并且从黄色变成紫色;也会反过来。
所以下面的代码在trigger
中定义两个状态,分别命名为open
和close
。其中也描述了两个状态的style。
@Component({
selector: 'app-open-close',
templateUrl: './open-close.component.html',
styleUrls: ['./open-close.component.css'],
animations: [
trigger('openClose', [
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
}))
]),
]
})
export class OpenCloseComponent implements OnInit {
// ...
}
光定义了状态还不够,因为动画需要平滑过渡才能有更好的用户体验。从状态1刷地一下直接变到状态2就感受不到动画效果,所以我们还需要定义过渡细节。
在下面的示例中,定义了两个过渡细节,一个是从open => closed
,这个状态变化过程花费1s;另一个是从closed => open
,花费0.5s。
@Component({
selector: 'app-open-close',
templateUrl: './open-close.component.html',
styleUrls: ['./open-close.component.css'],
animations: [
trigger('openClose', [
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
})),
transition('open => closed', [
animate('1s')
]),
transition('closed => open', [
animate('0.5s')
]),
]),
]
})
export class OpenCloseComponent implements OnInit {
// ...
}
我们可以在元素的属性中加上[@triggerName]="expression? state1: state2"
。
其中triggerName
就是之前定义的trigger
,这里应该写成[@openTrigger]
。
等号后面的表达式则是决定元素的状态变化。在这个示例中是通过按钮实现状态转变。
之前我们定义了动画的两个状态,分别叫open
和closed
,点击按钮,状态从open
转到closed
;再点击按钮,状态从closed
转到open
。
所以这里的expression可以写成[@openClose]="isOpen ? 'open' : 'closed'"
,其中isOpen
是变量,可以通过按钮点击事件改编。
下面是html的代码
<nav>
<button type="button" (click)="toggle()">Toggle Open/Closebutton>
nav>
<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!p>
div>
下面是完整的ts代码。
import { animate, state, style, transition, trigger } from '@angular/animations';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-open-close',
templateUrl: './open-close.component.html',
styleUrls: ['./open-close.component.css'],
animations: [
trigger('openClose', [
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'blue'
})),
transition('open => closed', [
animate('1s')
]),
transition('closed => open', [
animate('0.5s')
]),
]),
]
})
export class OpenCloseComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
isOpen = true;
toggle() {
this.isOpen = !this.isOpen;
}
}