Angular 2/4—路由动画教程及示例
Angular 2/4—路由动画教程及示例为了便于阅读,以下 Angular 统一代表 Angular2/4 版本,AngularJS 代表 Angular1.x 版本 在这个教程里,将告诉你如何使用 Angular 和 TypeScript 在路由转场间执行动画 项目代码地址:https://github.com/cornflourblue/angular2-animation-tutorial-example 查看使用 AngularJS 的路由动画示例:http://jasonwatmore.com/post/2016/01/20/angular-nganimate-tutorial-with-ui-router Angular 动画和 AngularJS 动画间的不同Angular 动画的工作方式与 AngularJS 中动画的工作方式是完全不同的,在 AngularJS 中通过 CSS 类钩子来实现视图切入和切出时的元素动画,但在 Angular 中,在你的组件中动画的执行是依靠一个方法的集合来实现的,这些方法包括 ( trigger,state,animate,transition,style ) ,集成在 @angular/animations 模块中 仍然使用 CSS 定义动画样式,但它们是写在 Typescript 中的 JSON 对象(TSON?)而不是 CSS / LESS 文件编写的,还有一种新的 Angular 动画 DSL(Domain Specific Language),创建它们用于定义不同的路由状态和路由之间转扬切换。 因为可以在Angular网站上找到所有这些详情信息,所以我不会太多地讲解所有新的动画系统的细节,而是将重点放在一个例子上以及如何在路由之间进行动画处理。 如果你觉得新的Angular动画系统让你痛苦的想撞墙,不要沮丧;很长一段时间内我也是抓耳挠腮很尴尬,但我仍然要掌握它! Angular 动画教程示例这里提供一个可以运转的教程示例应用,在顶级的标签切换使用淡入淡出的过渡,添加产品和修改产品页面使用滑入滑出的过渡动画。 在 Plunker 中查看示例 http://plnkr.co/edit/AfIB1i?p=preview 在本地运行 Angular 动画教程示例1,通过 https://nodejs.org/en/download/ 安装 NodeJS 和 NPM,命令行运行 node -v 和 npm -v 检测安装版本 2,下载项目源代码:https://github.com/cornflourblue/angular2-animation-tutorial-example 3,在项目的根目录 ( package.json 所在的目录),通过 npm install 命令安装相关依赖的包 4,通过在项目根目录运行 npm start 命令启动应用 让我们专注于动画我尝试制作一个真实领域的应用,所以它包含了少量的 Services 和一些其它的东西;但是在文中我将专注于动画和把这些动画怎样添加到 Angular 的路由中去。 在 app.module.ts 中导入 BrowserAnimationsModule 模块随着 Angular4 的发布,animations 模块已经从 Angular 核心模块中拆分到他们自己的模块中,所以,你不得不在 app.module.ts 文件顶部中引入 BrowserAnimationsModule 模块。 import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 并且在@NgModule元数据中,把 BrowserAnimationsModule 添加到 imports 列表中。 @NgModule({ imports:[ ...,BrowserANimationsMdoule ],... }) export class AppModule{} 第一个导入使 BrowserAnimationsModule 在 app.module.ts 文件中可用, 第二个导入使 BrowserAnimationsModule 中的方法可以在包含在 AppModule 中的其它组件中使用 定义你的 Angular 动画Animations 可以被直接定义在你的组件里,但我更喜欢把它们分离出来到它们自己的文件中,这样可以让这些动画在多处重用,并且可以使得你的组件代码更加清晰,更加易于维护和关注点分离。 在这个例子了中,我把动画放在了 app/_animations 文件夹中,我偏爱为无特征的文件夹加一个下划线前缀 [" _ "],目的是为了和那些特征性文件夹在最顶级目录做区分,特征文件夹用来存放应用的视图或者路由代码,像首页和产品页,无特征文件夹包含那些共享重用的代码,像 services,animations,directives,css等基本一切代码。 Angular 淡入动画在示例中,淡入动画被用于主页组件和产品列表组件 //从angular animations module 导入需要的动画方法 import {trigger,style} from '@angular/animations'; export const fadeInAnimation= //触发器名称,附加这个动画到元素上使用[@triggerName]语法 trigger('fadeInAnimation',[ //路由 '进入' 过渡 transition(':enter',[ //在过渡刚开始时的样式 style({opacity:0}),//动画和过渡结束时的样式 animate('.3s',style({opacity:1})) ]) ]) Angular 滑入滑出动画在示例中,滑入滑出动画被用在产品的添加和编辑组件上 //从angular animations module 导入需要的动画方法 import {trigger,style} from '@angular/animations'; export const slideInOutAnimation= //触发器名称,附加这个动画到元素上使用[@triggerName]语法 trigger('slideInOutAnimation',[ // 路由容器的最终状态样式 (host) state('*',style({ // 视图覆盖整个屏幕并且半透明背景 position: 'fixed',top: 0,left: 0,right: 0,bottom: 0,backgroundColor: 'rgba(0,0.8)' })),// 路由 '进入' 过渡 transition(':enter',[ // 过渡开始时的样式 style({ // 开始是内容区域相对于右侧的位置 // -400%代替100%,是由于负位置增加了元素的宽度 right: '-400%',// 开始时背景是全透明的 backgroundColor: 'rgba(0,0)' }) // 动画和结束时的样式状态 animate('.5s ease-in-out',style({ // 过渡到右侧为0,让内容进入视图 right: 0,// 过渡背景从透明到0.8 backgroundColor: 'rgba(0,0.8)' })) ]),// 路由'离开'过渡 transition(':leave',[ // 在过渡结束的动画和样式 animate('.5s ease-in-out',style({ // 过渡到右侧-400%,加了位移的内容宽度 right: '-400%',// 过渡背景透明度为0淡出 backgroundColor: 'rgba(0,0)' })) ]) ]) 附加 Angular 动画到你路由的组件上随着动画清晰的被分离进他们自己的文件,这样更容易附加它们到你的 Angular 路由,你需要做的就是导入动画到你想要添加的组件的 @Component 元数据中。 Angular 首页组件淡入动画示例中的添加了淡入动画的首页组件 import { Component } from '@angular/core'; // 导入淡入动画 import { fadeInAnimation } from '../_animations/index'; @Component({ moduleId: module.id.toString(),templateUrl: 'home.component.html',// 添加使用淡入动画在组件可用 animations: [fadeInAnimation],// 附加淡入动画到组件的最外层元素上 host: { '[@fadeInAnimation]': '' } }) export class HomeComponent {} Angular 添加淡入动画的产品列表组件示例中添加了淡入动画的产品列表组件 import { Component,OnInit,OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; import { ProductService,PubSubService } from '../_services/index'; // 导入淡入动画 import { fadeInAnimation } from '../_animations/index'; @Component({ moduleId: module.id.toString(),templateUrl: 'product-list.component.html',// 使淡入动画在组件中可用 animations: [fadeInAnimation],// 添加淡入动画到组件的最外层元素上 host: { '[@fadeInAnimation]': '' } }) export class ProductListComponent implements OnInit,OnDestroy { products: any[]; subscription: Subscription; constructor( private productService: ProductService,private pubSubService: PubSubService) { } deleteProduct(id: number) { this.productService.delete(id); this.loadProducts(); } ngOnInit() { this.loadProducts(); // 当更新时重载产品视图 this.subscription = this.pubSubService.on('products-updated').subscribe(() => this.loadProducts()); } ngOnDestroy() { // 取消订阅避免内存泄漏 this.subscription.unsubscribe(); } private loadProducts() { this.products = this.productService.getAll(); } } Angular 添加滑入滑出效果的产品添加编辑组件示例中添加滑入滑出效果的产品添加编辑组件 import { Component,OnInit } from '@angular/core'; import { Router,ActivatedRoute } from '@angular/router'; import { ProductService,PubSubService } from '../_services/index'; // 导入滑入滑出动画 import { slideInOutAnimation } from '../_animations/index'; @Component({ moduleId: module.id.toString(),templateUrl: 'product-add-edit.component.html',// 使滑入滑出动画在组件中可用 animations: [slideInOutAnimation],// 添加滑入滑出动画到组件最外层的元素上 host: { '[@slideInOutAnimation]': '' } }) export class ProductAddEditComponent implements OnInit { title = 'Add Product'; product: any = {}; constructor( private route: ActivatedRoute,private router: Router,private productService: ProductService,private pubSubService: PubSubService) { } ngOnInit() { let productId = Number(this.route.snapshot.params['id']); if (productId) { this.title = 'Edit Product'; this.product = this.productService.getById(productId); } } saveProduct() { // 保存产品 this.productService.save(this.product); // 重定向到products视图 this.router.navigate(['products']); // 发布产品更新事件 this.pubSubService.publish('products-updated'); } } 附注:Angular动画是基于标准的Web动画API(Web Animations API)构建的,它们在支持此API的浏览器中会用原生方式工作。至于其它浏览器,就需要一个填充库(polyfill)了。你可以从这里获取
|