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')),
])
]
})

可以在一个网站看到动画的速度

easings.net

可以参考:

css3中变形与动画(二)

css3中变形与动画(三)

三、关键帧

不是所有的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。

@HostBinding('@card') cardState = 'out';
把变量cardState绑定到@card属性上去。
相当于组件加上@card属性<app-project-item [@card]="cardState">

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">
<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动画的更多相关文章

  1. angular动画知识点以及代码样例

    原文地址 https://www.jianshu.com/p/4400174072e2 大纲 1.angular动画的相关概念 2.angular动画的绑定方式 3.angular动画代码实例 1.a ...

  2. Angular动画(ng-repeat)

    ng-repeat 动画 根据列表元素的插入与移除,触发相应的代码添加动画 <!doctype html> <html lang="en" ng-app=&quo ...

  3. Angular 动画

    1.先做一个简单的例子  =>  定义一个div 从open渐变成closed ts:定义一个触发器 openClose,有两个状态 open 和 closed,均有对应的样式,再定义装换函数 ...

  4. Angular动画——路由动画及高阶动画函数

    一.路由动画 路由动画需要在host元数据中指定触发器.动画注意不要过多,否则适得其反. 内容优先,引导用户去注意到某个内容.动画只是辅助手段. 定义一个进场动画,一个离场动画. 因为进场动画和离场动 ...

  5. Angular动画(ng-class)

    ng-class 同 触发的是 addClass//当给元素添加一个class时触发, removeClass //把元素的class移除时触发 <ul ng-style="ulWid ...

  6. Angular 小试牛刀[1]:Getting Started

    首先,Angular2 与 Angular1.x 版本没有多大关系,甚至可以说是两个完全不一样的框架,故 Angular 指的是 Angular2 及以上的版本.而 Angular 与 TypeScr ...

  7. 动态创建angular组件实现popup弹窗

    承接上文,本文将从一个基本的angular启动项目开始搭建一个具有基本功能.较通用.低耦合.可扩展的popup弹窗(脸红),主要分为以下几步: 基本项目结构搭建 弹窗服务 弹窗的引用对象 准备作为模板 ...

  8. 从源码看 angular/material2 中 dialog模块 的实现

    本文将探讨material2中popup弹窗即其Dialog模块的实现. 使用方法 引入弹窗模块 自己准备作为模板的弹窗内容组件 在需要使用的组件内注入 MatDialog 服务 调用 open 方法 ...

  9. angular学习第1步

    #### 最专业,最全面的angular的学习文档 https://www.jianshu.com/p/f0f81a63cbcb ### https://www.cnblogs.com/xiaowei ...

随机推荐

  1. git学习02 - log查看&版本回退

    1.查看更新记录 git log /  git log --pretty=oneline D:\learn\git_test>git log commit a915e7b12076673d778 ...

  2. 使用sshpass同时更新一台ubuntu和一台CentOS

    1.在ubuntu上安装sshpass sudo apt install sshpass 2.分别在两台的root路径下放上升级脚本: cent:/root/upgrade.sh #!/bin/bas ...

  3. elasticsearch中head插件中的定制增加用户名密码范例

    在head插件目录下一般 在 elasticsearch目录下的 plugins\head目录 下 在 或 plugins\head\site目录下 有 一个index.html文件.把这个文件用下面 ...

  4. 超越村后端开发(2:新建models.py+xadmin的引入)

    1.新建Model 1.users数据 1.在apps/users/models.py中: from datetime import datetime from django.db import mo ...

  5. Qt: 执行cmd命令;

    QProcess p(NULL); p.setWorkingDirectory(szAppPath+"/database"); //指定工作路径,这个地方一定要设置: p.star ...

  6. blackbox_exporter介绍

    Blackbox Exporter是Prometheus社区提供的官方黑盒监控解决方案,其允许用户通过:HTTP.HTTPS.DNS.TCP以及ICMP的方式对网络进行探测. 1.安装部署 cd /u ...

  7. Repeater取不到服务端控件

    <td>      <asp:Button ID="Button1" runat="server" Text="查看" O ...

  8. 通过DeviceIoControl读磁盘的方式读取独占文件内容

    前言 windows操作系统中常见的一个文件存储系统是NTFS.在这个文件系统中MFT是它的核心.             图一 MFT是一个数据结构,上图是它的结构,它主要用来存放每个文件和目录在磁 ...

  9. 微信小程序中使用 <web-view> 内嵌 H5 时,登录问题的处理方法

    在微信小程序的开发中,经常遇到需要使用 <web-view></web-view> 内嵌 H5 的需求.在这种需求中比较棘手的问题应该就是登录状态的判断了,小程序中的登录状态怎 ...

  10. spark2.2.1安装、pycharm连接spark配置

    一.单机版本Spark安装 Win10下安装Spark2.2.1 1. 工具准备 JDK 8u161 with NetBeans 8.2: http://www.oracle.com/technetw ...