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 ...
随机推荐
- 「NOI2013」树的计数 解题报告
「NOI2013」树的计数 这什么神题 考虑对bfs重新编号为1,2,3...n,然后重新搞一下dfs序 设dfs序为\(dfn_i\),dfs序第\(i\)位对应的节点为\(pos_i\) 一个暴力 ...
- 戏说java与web
slmgr.vbs /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43教育版换回企业版 搜百度网盘 http://www.pansoso.com/ https://m.zhangl ...
- VO、DTO、DO、PO
领域模型中的实体类可细分为4种类型:VO.DTO.DO.PO. PO(Persistent Object):持久化对象,表示持久层的数据结构(如数据库表): DO(Domain Object):领域对 ...
- opencv+codeblocks +anaconda
study from : https://www.jianshu.com/p/c16b7c870356 #include <cstdio> #include <cstdlib> ...
- C#编程中的Image/Bitmap与base64的转换及 Base-64 字符数组或字符串的长度无效问题 解决
最近用base64编码传图片遇到了点问题,总结下. 首先总结下base64编码的逻辑,来自网络:https://www.cnblogs.com/zhangchengye/p/5432276.html ...
- Linux下的sudo及配置
sudo的常用命令 man sudoers # 参阅帮助 visudo # 编辑sudoers文件的命令 sudo -l # 查看可执行或禁止执行的命令 sudo -u user1 /bin/ls # ...
- js下拉框:从数组中筛选出匹配的数据
handleChange(val) { let obj = {} // 遍历数组 obj = this.options.find(item => { // 筛选出匹配的数据 return ite ...
- 转载:在做datatable时候查询数据和条数只用一次sql就可以解决需求
前言:最近用datatable处理数据比较多,所以在使用时候想提升性能 select * from t_hr_leave SELECT FOUND_ROWS() //返回查询记录的总数 select ...
- js手写'Promise'
/* * pending:初始化成功 * fulfilled:成功 * rejected:失败 * */ function Promise(executor) {// 执行器 this.status ...
- [置顶]Python开发之路
阅读目录 第一篇:python入门 第二篇:数据类型.字符编码.文件处理 第三篇:函数 第四篇:模块与包 第五篇:常用模块 第六篇:面向对象 第七篇:面向对象高级 第八篇:异常处理 第九篇:网络编 ...