Angular动画
Angular动画基于W3C的Web Animations标准。不在Angular Core中了。
组件里面定义一个或多个触发器trigger,每个触发器有一系列的状态和过渡效果来实现。
动画其实就是从一个状态过渡到另一个状态。状态本身包含形状,颜色,大小等。
核心是State和Transition。
State就是定义每一帧状态
Transition是定义一帧到下一帧如何过渡。
transition中定义animation,Animate规定了具体怎样过渡,比如时间,过渡的速度等。Animate有多个重载形式。
一、例子
先安装动画库
npm i --save @angular/animations
导入module
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
imports: [
...
BrowserAnimationsModule, //放在最后导入
],
定义一个宽度100的黑色正方形。
.square{
width: 100px;
height: 100px;
background-color:black;
align-items: center;
}
在animations元数据中定义一个触发器,触发器名字叫square。html的响应元素中[@square]是动画的触发器的名字。这个变量或者函数在某一情况下改变元素的状态。
<div class="square" [@square]="squareState" (click)="onClick()">
</div>
触发器有2个重要组成State和Transition。
State定义状态,在不同的状态下应用不同的样式。通过style把一些css样式应用于实现动画的元素,定义好某一帧的颜色,大小,位置。
Transition负责在不同状态切换时候做怎样的变换,定义如何迁移状态,如何过渡。
import { trigger, state, transition, style, animate } from '@angular/animations'; @Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
animations: [
trigger('square', [
state('green', style({ 'background-color': 'green','height':'100px','transform':'translateX(0)' })),
state('red', style({ 'background-color': 'red','height':'50px' ,'transform':'translateX(100%)'})),
transition('green=>red', animate('.2s 1s')),//动画持续的时间,延迟多久开始
transition('red=>green', animate()),
])
]
})
export class AppComponent {
squareState:string; onClick(){
this.squareState = this.squareState ==='red'?'green':'red';
}
}
二、缓动函数
动画执行时候的速度,使其看起来更加真实。
因为不是所有的动画都是匀速的,可以先加速后减速。
例如:皮球下落,先是越调越快,撞到地上后回弹最终才又碰到地板。
例子:
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
animations: [
trigger('square', [
state('green', style({ 'background-color': 'green','height':'100px','transform':'translateY(-100%)' })),
state('red', style({ 'background-color': 'red','height':'100px' ,'transform':'translateY(100%)'})),
transition('green=>red', animate('.8s ease-in')),
transition('red=>green', animate('.8s ease-out')),
])
]
})
可以在一个网站看到动画的速度
可以参考:
三、关键帧
不是所有的cubic-bezier函数都能在css动画中得到支持,可以通过关键帧来实现。
keyframes是一个数组,里面定义每一帧的样式。
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
animations: [
trigger('square', [
state('green', style({ 'background-color': 'green','height':'100px','transform':'translateY(-100%)' })),
state('red', style({ 'background-color': 'red','height':'100px' ,'transform':'translateY(100%)'})),
transition('green=>red', animate('.8s ease-in')),
transition('red=>green', animate(, keyframes([
style({transform:'translateY(100%)'}),
style({transform:'translateY(98%)'}),
style({transform:'translateY(95%)'}),
style({transform:'translateY(90%)'}),
style({transform:'translateY(80%)'}),
style({transform:'translateY(60%)'}),
style({transform:'translateY(30%)'}),
style({transform:'translateY(0)'}),
style({transform:'translateY(-10%)'}),
style({transform:'translateY(-5%)'}),
style({transform:'translateY(-2%)'}),
style({transform:'translateY(0)'}),
style({transform:'translateY(10%)'}),
style({transform:'translateY(15%)'}),
style({transform:'translateY(-15%)'}),
style({transform:'translateY(-40%)'}),
style({transform:'translateY(-80%)'}),
style({transform:'translateY(-90%)'}),
style({transform:'translateY(-95%)'})
])))
])
]
})
四、实际应用
把动画分离出来,不要和组件强耦合。
新建一个文件夹animate放所有的动画文件。
1、card相关的动画——绑定到宿主
新建一个card.animate.ts放card相关的动画。
import { trigger, state, transition, style, animate ,keyframes} from '@angular/animations'; export const cardAnim = trigger('card',[
state('out',style({transform:'scale(1)','box-shadow':'none'})),
state('hover',style({transform:'scale(1.1)','box-shadow':'3px 3px 5px 6px #ccc'})),
transition('out => hover',animate('200ms ease-in')),
transition('hover => out',animate('200ms ease-out'))
]);
在project-item里使用动画。
1、从@angular/core里导入HostBinding。
2、引入另外一个HostListener
监听鼠标enter和leave的事件
@HostListener('mouseenter', ['$event.target'])
onMouseEnter(target) {
this.cardState = 'hover';
} @HostListener('mouseleave', ['$event.target'])
onMouseLeave(target) {
this.cardState = 'out';
}
import { Component, OnInit, Input, EventEmitter, Output ,HostBinding ,HostListener} from '@angular/core';
import { cardAnim } from '../../animate/card.animate' @Component({
selector: 'app-project-item',
templateUrl: './project-item.component.html',
styleUrls: ['./project-item.component.scss'],
animations:[
cardAnim
]
})
export class ProjectItemComponent implements OnInit { @Input() item;
@Output() onInvite = new EventEmitter<void>();
@Output() onEdit = new EventEmitter<void>();
@Output() onDelete = new EventEmitter<void>();
@HostBinding('@card') cardState = 'out'; constructor() { } ngOnInit() {
} @HostListener('mouseenter')
onmouseenter(){
this.cardState = 'hover'
} @HostListener('mouseleave')
onmouseleave(){
this.cardState = 'out'
} onInviteClick() {
this.onInvite.emit();
}
onEditClick() {
this.onEdit.emit();
}
onDeleteClick(){
this.onDelete.emit();
}
}
2、task相关的动画——绑定到部分元素
不是组件本身的动画,而是组件中一部分元素的动画。
新建一个item.animate.ts放task相关的动画
import { trigger, state, transition, style, animate ,keyframes} from '@angular/animations'; export const itemAnim = trigger('item',[
state('in',style({'border-left-width':'3px'})),
state('out',style({'border-left-width':'8px'})),
transition('in => out',animate('200ms ease-in')),
transition('out => in',animate('200ms ease-out'))
]);
在test-item中使用
import { Component, OnInit, Input, EventEmitter, Output, HostListener } from '@angular/core';
import {itemAnim} from '../../animate/item.animate'; @Component({
selector: 'app-task-item',
templateUrl: './task-item.component.html',
styleUrls: ['./task-item.component.scss'],
animations:[
itemAnim
]
})
export class TaskItemComponent implements OnInit { @Input() item;
@Input() avatar: string;
@Output() taskClick = new EventEmitter<void>();
widerPriority = 'in'; constructor() { } ngOnInit() {
this.avatar = this.item.owner ? this.item.owner.avatar : 'unassigned';
} @HostListener('mouseenter')
onmouseenter(){
this.widerPriority='out';
}
@HostListener('mouseleave')
onmouseleave(){
this.widerPriority='in';
} onItemClick() {
this.taskClick.emit();
}
onCheckBoxClick(event: Event): void {
event.stopPropagation();
} }
在模版中用
<mat-list-item class="container"
[@item]="widerPriority"
[ngClass]="{
'priority-normal':item.priority===3,
'priority-important':item.priority===2,
'priority-emergency':item.priority===1
}"
(click)=onItemClick()>
<mat-checkbox [checked]="item.completed" class="status" (click)="onCheckBoxClick($event)"> </mat-checkbox>
<div class="content" mat-line [ngClass]="{'completed':item.completed}">
<span [matTooltip]="item.desc">{{item.desc}}</span>
</div>
<div class="bottom-bar" mat-line>
<span class="due-date" *ngIf="item.dueDate">
{{item.dueDate | date:"yy-MM-dd"}}
</span>
<mat-icon *ngIf="item.reminder">
alarm
</mat-icon>
</div>
<mat-icon [svgIcon]="avatar" mat-list-avatar class="avatar"> </mat-icon>
</mat-list-item>
效果
Angular动画的更多相关文章
- angular动画知识点以及代码样例
原文地址 https://www.jianshu.com/p/4400174072e2 大纲 1.angular动画的相关概念 2.angular动画的绑定方式 3.angular动画代码实例 1.a ...
- Angular动画(ng-repeat)
ng-repeat 动画 根据列表元素的插入与移除,触发相应的代码添加动画 <!doctype html> <html lang="en" ng-app=&quo ...
- Angular 动画
1.先做一个简单的例子 => 定义一个div 从open渐变成closed ts:定义一个触发器 openClose,有两个状态 open 和 closed,均有对应的样式,再定义装换函数 ...
- Angular动画——路由动画及高阶动画函数
一.路由动画 路由动画需要在host元数据中指定触发器.动画注意不要过多,否则适得其反. 内容优先,引导用户去注意到某个内容.动画只是辅助手段. 定义一个进场动画,一个离场动画. 因为进场动画和离场动 ...
- Angular动画(ng-class)
ng-class 同 触发的是 addClass//当给元素添加一个class时触发, removeClass //把元素的class移除时触发 <ul ng-style="ulWid ...
- Angular 小试牛刀[1]:Getting Started
首先,Angular2 与 Angular1.x 版本没有多大关系,甚至可以说是两个完全不一样的框架,故 Angular 指的是 Angular2 及以上的版本.而 Angular 与 TypeScr ...
- 动态创建angular组件实现popup弹窗
承接上文,本文将从一个基本的angular启动项目开始搭建一个具有基本功能.较通用.低耦合.可扩展的popup弹窗(脸红),主要分为以下几步: 基本项目结构搭建 弹窗服务 弹窗的引用对象 准备作为模板 ...
- 从源码看 angular/material2 中 dialog模块 的实现
本文将探讨material2中popup弹窗即其Dialog模块的实现. 使用方法 引入弹窗模块 自己准备作为模板的弹窗内容组件 在需要使用的组件内注入 MatDialog 服务 调用 open 方法 ...
- angular学习第1步
#### 最专业,最全面的angular的学习文档 https://www.jianshu.com/p/f0f81a63cbcb ### https://www.cnblogs.com/xiaowei ...
随机推荐
- git学习02 - log查看&版本回退
1.查看更新记录 git log / git log --pretty=oneline D:\learn\git_test>git log commit a915e7b12076673d778 ...
- 使用sshpass同时更新一台ubuntu和一台CentOS
1.在ubuntu上安装sshpass sudo apt install sshpass 2.分别在两台的root路径下放上升级脚本: cent:/root/upgrade.sh #!/bin/bas ...
- elasticsearch中head插件中的定制增加用户名密码范例
在head插件目录下一般 在 elasticsearch目录下的 plugins\head目录 下 在 或 plugins\head\site目录下 有 一个index.html文件.把这个文件用下面 ...
- 超越村后端开发(2:新建models.py+xadmin的引入)
1.新建Model 1.users数据 1.在apps/users/models.py中: from datetime import datetime from django.db import mo ...
- Qt: 执行cmd命令;
QProcess p(NULL); p.setWorkingDirectory(szAppPath+"/database"); //指定工作路径,这个地方一定要设置: p.star ...
- blackbox_exporter介绍
Blackbox Exporter是Prometheus社区提供的官方黑盒监控解决方案,其允许用户通过:HTTP.HTTPS.DNS.TCP以及ICMP的方式对网络进行探测. 1.安装部署 cd /u ...
- Repeater取不到服务端控件
<td> <asp:Button ID="Button1" runat="server" Text="查看" O ...
- 通过DeviceIoControl读磁盘的方式读取独占文件内容
前言 windows操作系统中常见的一个文件存储系统是NTFS.在这个文件系统中MFT是它的核心. 图一 MFT是一个数据结构,上图是它的结构,它主要用来存放每个文件和目录在磁 ...
- 微信小程序中使用 <web-view> 内嵌 H5 时,登录问题的处理方法
在微信小程序的开发中,经常遇到需要使用 <web-view></web-view> 内嵌 H5 的需求.在这种需求中比较棘手的问题应该就是登录状态的判断了,小程序中的登录状态怎 ...
- spark2.2.1安装、pycharm连接spark配置
一.单机版本Spark安装 Win10下安装Spark2.2.1 1. 工具准备 JDK 8u161 with NetBeans 8.2: http://www.oracle.com/technetw ...