详解Angular路由动画及高阶动画函数

一、路由动画

路由动画需要在host元数据中指定触发器。动画注意不要过多,否则适得其反。

内容优先,引导用户去注意到某个内容。动画只是辅助手段。

在router.animate.ts中定义一个进场动画,一个离场动画。

因为进场动画和离场动画用的特别频繁,有一个别名叫:enter和:leave。

import { trigger, state, transition, style, animate} from '@angular/animations';

export const slideToRight = trigger('routeAnim',[
    state('void',style({'position':'fixed','width':'100%','height':'100%'})),
    state('*',style({'position':'fixed','width':'100%','height':'80%'})),
    transition('void => *',[
        style({transform:'translateX(-100%)'}),
        animate('.5s ease-in-out', style({transform:'translateX(0)'}))
    ]),
    transition('* => void',[
        style({transform:'translateX(0)'}),
        animate('.5s ease-in-out', style({transform:'translateX(100%)'}))
    ]),
]);

在project-list中使用路由动画。

import { Component, OnInit , HostBinding } from "@angular/core";
import { MatDialog } from "@angular/material";
import { NewProjectComponent } from "../new-project/new-project.component";
import { InviteComponent } from '../invite/invite.component';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import {slideToRight} from '../../animate/router.animate'

@Component({
  selector: "app-project-list",
  templateUrl: "./project-list.component.html",
  styleUrls: ["./project-list.component.scss"],
  animations:[
    slideToRight
  ]
})
export class ProjectListComponent implements OnInit {
  @HostBinding('@routeAnim') state;

  projects = [
    {
      name: "企业协作平台",
      desc: "这是一个企业内部项目",
      coverImg: "assets/images/covers/0.jpg"
    },
    {
      name: "自动化测试项目",
      desc: "这是一个企业内部项目",
      coverImg: "assets/images/covers/2.jpg"
    }
  ];
  constructor(private dialog: MatDialog) { }

  ngOnInit() { }

  openNewProjectDialog() {
    // this.dialog.open(NewProjectComponent,{data:'this is a dialog'});
    const dialogRef = this.dialog.open(NewProjectComponent, {
      data: { title: '新建项目' }
    });
    dialogRef.afterClosed().subscribe((result) => {
      console.log(result);
    });
  }

  lauchInviteDialog() {
    const dialogRef = this.dialog.open(InviteComponent);
  }

  lauchUpdateDialog() {
    const dialogRef = this.dialog.open(NewProjectComponent, {
      data: { title: '编辑项目' }
    });
  }

  lauchConfimDialog() {
    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      data: { title: '编辑项目', content: '您确认删除该项目吗?' }
    });
  }
}

在task-home中使用路由动画。

import { Component, OnInit , HostBinding } from "@angular/core";
import { NewTaskComponent } from "../new-task/new-task.component";
import { MatDialog } from "@angular/material";
import { CopyTaskComponent } from "../copy-task/copy-task.component";
import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component";
import { NewTaskListComponent } from "../new-task-list/new-task-list.component";
import {slideToRight} from '../../animate/router.animate';

@Component({
  selector: "app-task-home",
  templateUrl: "./task-home.component.html",
  styleUrls: ["./task-home.component.scss"],
  animations:[
    slideToRight
  ]
})
export class TaskHomeComponent implements OnInit {
  constructor(private dialog: MatDialog) {}

  @HostBinding('@routeAnim') state;
  ngOnInit() {}

  launchNewTaskDialog() {
    // this.dialog.open(NewTaskComponent);
    const dialogRef = this.dialog.open(NewTaskComponent, {
      data: { title: "新建任务" }
    });
  }
  lauchCopyTaskDialog() {
    const dialogRef = this.dialog.open(CopyTaskComponent, {
      data: { lists: this.lists }
    });
  }

  launchUpdateTaskDialog(task) {
    const dialogRef = this.dialog.open(NewTaskComponent, {
      data: { title: "修改任务", task: task }
    });
  }

  launchConfirmDialog() {
    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      data: { title: "删除任务列表", content: "您确定要删除该任务列表吗?" }
    });
  }

  launchEditListDialog() {
    const dialogRef = this.dialog.open(NewTaskListComponent, {
      data: { title: "更改列表名称" }
    });
    dialogRef.afterClosed().subscribe(result => console.log(result));
  }
  launchNewListDialog() {
    const dialogRef = this.dialog.open(NewTaskListComponent, {
      data: { title: "新建列表名称" }
    });
    dialogRef.afterClosed().subscribe(result => console.log(result));
  }
  lists = [
    {
      id: 1,
      name: "待办",
      tasks: [
        {
          id: 1,
          desc: "任务一: 去星巴克买咖啡",
          completed: true,
          priority: 3,
          owner: {
            id: 1,
            name: "张三",
            avatar: "avatars:svg-11"
          },
          dueDate: new Date(),
          reminder: new Date()
        },
        {
          id: 2,
          desc: "任务一: 完成老板布置的PPT作业",
          completed: false,
          priority: 2,
          owner: {
            id: 2,
            name: "李四",
            avatar: "avatars:svg-12"
          },
          dueDate: new Date()
        }
      ]
    },
    {
      id: 2,
      name: "进行中",
      tasks: [
        {
          id: 1,
          desc: "任务三: 项目代码评审",
          completed: false,
          priority: 1,
          owner: {
            id: 1,
            name: "王五",
            avatar: "avatars:svg-13"
          },
          dueDate: new Date()
        },
        {
          id: 2,
          desc: "任务一: 制定项目计划",
          completed: false,
          priority: 2,
          owner: {
            id: 2,
            name: "李四",
            avatar: "avatars:svg-12"
          },
          dueDate: new Date()
        }
      ]
    }
  ];
}

定义路由

<mat-list-item [routerLink]="['/project']">
    <mat-icon mat-list-icon svgIcon="projects"></mat-icon>
    <h4 mat-line>项目首页</h4>
    <p mat-line mat-subheader> 查看您的所有项目</p>
  </mat-list-item>
  <mat-list-item [routerLink]="['/task']">
    <mat-icon mat-list-icon svgIcon="projects"></mat-icon>
    <h4 mat-line>任务首页</h4>
    <p mat-line mat-subheader> 查看您的所有项目</p>
  </mat-list-item>

注意:一定要用HostBinding形式。

二、Group

用于同时进行一组动画变换

group([animate(...),animate(...)...])接收一个数组,数组里写多个动画。

import { trigger, state, transition, style, animate, group} from '@angular/animations';

export const slideToRight = trigger('routeAnim',[
    state('void',style({'position':'fixed','width':'100%','height':'80%'})),
    state('*',style({'position':'fixed','width':'100%','height':'80%'})),
    transition(':enter',[
        style({transform:'translateX(-100%)',opacity:'0'}),
        group([
            animate('.5s ease-in-out', style({transform:'translateX(0)'})),
            animate('.3s ease-in', style({opacity:1}))
        ])
    ]),
    transition(':leave',[
        style({transform:'translateX(0)',opacity:'1'}),
        group([
            animate('.5s ease-in-out', style({transform:'translateX(100%)'})),
            animate('.3s ease-in', style({opacity:0}))
        ])
    ]),
]);

三、Query & Stagger

Query用于父节点寻找子节点,把动画应用到选中元素。非常强大。

Stagger指定有多个满足Query的元素,每个的动画之间有间隔。

做一个示例:新建的时候同时新建2个项目,两个新建出的项目的动画依次产生,第一个完成后才开始第二个。

建立list.animate.ts

进场动画,先隐藏起来,通过stagger间隔1000s做一个1s的动画。

import { trigger, state, transition, style, animate, query, animation,stagger} from '@angular/animations';

export const listAnimation = trigger('listAnim', [
    transition('* => *', [
      query(':enter', style({opacity: 0}), { optional: true }), //加入optional为true,后面的状态动画都是可选的
      query(':enter', stagger(1000, [
        animate('1s', style({opacity: 1}))
      ]), { optional: true }),
      query(':leave', style({opacity: 1}), { optional: true }),
      query(':leave', stagger(1000, [
        animate('1s', style({opacity: 0}))
      ]), { optional: true })
    ])
  ]);

在project_list中使用

应用query动画一般都是跟*ngFor在一起的,需要外面套一层div。

<div class="container" [@listAnim]="projects.length">
  <app-project-item *ngFor="let project of projects" [item]="project"
  class="card"
  (onInvite)="lauchInviteDialog()"
  (onEdit)="lauchUpdateDialog()"
  (onDelete)="lauchConfimDialog(project)">
  </app-project-item>
</div>
<button class="ab-buttonmad-fab fab-button" mat-fab type="button" (click)="openNewProjectDialog()">
  <mat-icon>add</mat-icon>
</button>

修改对应的css

// :host{
//     display: flex;
//     flex-direction: row;
//     flex-wrap: wrap;
// }

//把host改为div
.container{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

修改一下component

import { Component, OnInit , HostBinding } from "@angular/core";
import { MatDialog } from "@angular/material";
import { NewProjectComponent } from "../new-project/new-project.component";
import { InviteComponent } from '../invite/invite.component';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import {slideToRight} from '../../animate/router.animate'
import { listAnimation } from '../../animate/list.animate';
import { projection } from '@angular/core/src/render3';

@Component({
  selector: "app-project-list",
  templateUrl: "./project-list.component.html",
  styleUrls: ["./project-list.component.scss"],
  animations:[
    slideToRight,listAnimation  //第一步,导入listAnimation
  ]
})
export class ProjectListComponent implements OnInit {
  @HostBinding('@routeAnim') state;

  //第二步,改造一下数组,加id
  projects = [
    {
      id:1,
      name: "企业协作平台",
      desc: "这是一个企业内部项目",
      coverImg: "assets/images/covers/0.jpg"
    },
    {
      id:2,
      name: "自动化测试项目",
      desc: "这是一个企业内部项目",
      coverImg: "assets/images/covers/2.jpg"
    }
  ];
  constructor(private dialog: MatDialog) { }

  ngOnInit() { }

  //第三步,新增元素时hard code一下
  openNewProjectDialog() {
    // this.dialog.open(NewProjectComponent,{data:'this is a dialog'});
    const dialogRef = this.dialog.open(NewProjectComponent, {
      data: { title: '新建项目' }
    });
    dialogRef.afterClosed().subscribe((result) => {
      console.log(result);
      this.projects = [...this.projects,
        {id:3,name:'一个新项目',desc:'这是一个新项目',coverImg:"assets/images/covers/3.jpg"},
        {id:4,name:'又一个新项目',desc:'这是又一个新项目',coverImg:"assets/images/covers/4.jpg"}]
    });
  }

  lauchInviteDialog() {
    const dialogRef = this.dialog.open(InviteComponent);
  }

  lauchUpdateDialog() {
    const dialogRef = this.dialog.open(NewProjectComponent, {
      data: { title: '编辑项目' }
    });
  }

  //第四步,改造一下删除项目
  lauchConfimDialog(project) {
    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      data: { title: '删除项目', content: '您确认删除该项目吗?' }
    });
    dialogRef.afterClosed().subscribe(result=>{
      console.log(result);
      this.projects=this.projects.filter(p=>p.id!=project.id);
    });
  }
}

Stagger使得在多个元素时候,动画交错开,而不是一起。

以上就是详解Angular路由动画及高阶动画函数的详细内容,更多关于Angular路由动画及高阶动画函数的资料请关注我们其它相关文章!

(0)

相关推荐

  • AngularJS中实现显示或隐藏动画效果的方式总结

    AngularJS 是一组用于创建单页Web应用的丰富框架,给构建丰富交互地应用带来了所有需要的功能.其中一项主要的特性就是Angular带来了对动画的支持. 本篇体验在AngularJS中实现在"显示/隐藏"这2种状态切换间添加动画效果. 通过CSS方式实现显示/隐藏动画效果 思路: →npm install angular-animage →依赖:var app = angular.module("app",["ngAnimate"]); →

  • 利用CSS3在Angular中实现动画

    废话不多说了,直接给大家贴实例代码. 直接看例子: <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>ngAnimate插件1</title> <script type=&quo

  • 基于Angular.js实现的触摸滑动动画实例代码

    先上图: 这个主要用到是angular-touch.js中封装好的ng-swipe-left,ng-swipe-right,向左或向右的触摸事件.结合css3的transition实现的动画.ng-class为切换写好的动画的className. <!DOCTYPE HTML> <html ng-app="myapp"> <head> <meta http-equiv="content-type" content="

  • 在AngularJS应用中实现一些动画效果的代码

    在Angular当中,CSS和JavaScript之间唯一的区别就是它们的定义.没有什么区别妨碍到被定义的动画被使用.首先,我们需要加载ngAnimate模块到我们应用的root模块当中. angular.module('coursesApp', ['ngAnimate']); 而所有将被处理的JavaScript动画事件依然保持不变.以下是一个直接支持的动画列表和它们对应的不同行为: 指令事件集 ng-view ng-include ng-switch ng-if  enter leave n

  • Angular4如何自定义首屏的加载动画详解

    前言 相信大家都知道,在默认情况下,Angular应用程序在首次加载根组件时,会在浏览器的显示一个loading... 我们可以轻松地将loading修改成我们自己定义的动画.下面话不多说,来一起看看详细的介绍: 这是我们要实现首次加载的效果: 根组件标签中的内容 请注意:在你的入口文件index.html中,默认的loading...只是插入到根组件标签之间: <!doctype html> <html> <head> <meta charset="u

  • Angular2搜索和重置按钮过场动画

    需求:给项目管理页面加上搜索和重置的过场动画. 最先想到的就是利用angular2的animations属性. // project.component.ts import {trigger, state, style, animate, transition} from '@angular/animations'; @Component({ selector: 'projects', template: require('./projects.html'), styleUrls: ['./pr

  • 给angular加上动画效遇到的问题总结

    加入"动效"是让用户对应用的行为进行感知的一种有效手段."列表"是应用中最常使用的一种界面形式,经常会有添加行,删除行,移动行这些操作.设想添加的操作很简单,删除时从大到小,然后消失:添加时从小到大:移动就是先删除再添加.感觉上并不复杂,应该利用CSS的transition就能搞定,可是实际做起来发现有不少问题要处理,下面一一道来. 来些简单的测试 1.最初的版本 <div class='list'> <div class='row-1'>r

  • 使用ngView配合AngularJS应用实现动画效果的方法

    AngularJS 提供了一个很棒的方式来创建单页app.正是由于这个原因,使得我们的站点看起来更像是一个原生的手机程序.为了使它看起来更像是原生的程序,我们可以使用 ngAnimate module 为它添加过渡和动画效果. 这个模块可以使我们创建漂亮的程序.今天,我们将要看一下如何为 ng-view 添加动画效果. 我们要构建什么 我们假设我们有一个单页面的程序,并且想为这个页面添加动画效果.点击某一个链接会将一个试图滑出,同时将另一个试图滑入. 我们将会使用: 使用 ngRoute 来为我

  • Angular4.0动画操作实例详解

    本文实例讲述了Angular4.0动画操作.分享给大家供大家参考,具体如下: 粗略的记录一下angular4的动画 先看一下angular中文网关于这个给的例子. 有两个组件home,about. 路径配置什么的这里就不细说了,之前的博文有说过,我就贴一下代码,很好理解的, 需要import的东西我先说一下,我只贴了使用动画要用的东西,其他的我省略了, app.module.ts import { BrowserModule } from '@angular/platform-browser';

  • 详解Angular路由动画及高阶动画函数

    一.路由动画 路由动画需要在host元数据中指定触发器.动画注意不要过多,否则适得其反. 内容优先,引导用户去注意到某个内容.动画只是辅助手段. 在router.animate.ts中定义一个进场动画,一个离场动画. 因为进场动画和离场动画用的特别频繁,有一个别名叫:enter和:leave. import { trigger, state, transition, style, animate} from '@angular/animations'; export const slideToR

  • 详解Angular路由之子路由

    目录 一.子路由语法 二.实例 1.新建2个组件修改其内容 2.修改路由配置 3.修改product.component.ts的模版 一.子路由语法 二.实例 在商品详情页面,除了显示商品id信息,还显示了商品描述,和销售员的信息. 通过子路由实现商品描述组件和销售员信息组件展示在商品详情组件内部. 1.新建2个组件修改其内容 ng g component productDesc ng g component sellerInfo 重点是修改销售员信息组件,显示销售员ID. import { C

  • 详解Go语言如何利用高阶函数写出优雅的代码

    目录 前言 问题 白银 黄金 王者 总结 前言 go项目中经常需要查询db,按照以前java开发经验,会根据查询条件写很多方法,如: GetUserByUserID GetUsersByName GetUsersByAge 每一种查询条件写一个方法,这种方式对外是挺好的,对外遵循严格原则,让每个对外的方法接口是明确的.但是对内的话,应该尽可能的通用,做到代码复用,少写代码,让代码看起来更优雅.整洁. 问题 在review代码的时候,针对上面3个方法,一般写法是 func GetUserByUse

  • 详解Angular路由之路由守卫

    一.路由守卫 当用户满足一定条件才被允许进入或者离开一个路由. 路由守卫场景: 只有当用户登录并拥有某些权限的时候才能进入某些路由. 一个由多个表单组成的向导,例如注册流程,用户只有在当前路由的组件中填写了满足要求的信息才可以导航到下一个路由. 当用户未执行保存操作而试图离开当前导航时提醒用户. Angular提供了一些钩子帮助控制进入或离开路由.这些钩子就是路由守卫,可以通过这些钩子实现上面场景. CanActivate: 处理导航到某路由的情况. CanDeactivate: 处理从当前路由

  • 详解python内置常用高阶函数(列出了5个常用的)

    高阶函数是在Python中一个非常有用的功能函数,所谓高阶函数就是一个函数可以用来接收另一个函数作为参数,这样的函数叫做高阶函数. python内置常用高阶函数: 一.函数式编程 •函数本身可以赋值给变量,赋值后变量为函数: •允许将函数本身作为参数传入另一个函数: •允许返回一个函数. 1.map()函数 是 Python 内置的高阶函数,它接收一个函数 f 和一个 list, 并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回 def add(x): ret

  • 详解Angular路由 ng-route和ui-router的区别

    什么是路由? 路由是AngularJS构建单页面应用的基础. 路由,就是网络数据或者请求进行分发的一个网络组件. 路由就是一个用于请求URL分发和跳转的一个应用组件,Angular中通过$routeProvider路由服务提供者进行核心的配置处理. ng路由 ng 路由是 AngularJS 官方提供的一种简单的路由操作. ng 路由主要分三个组成部分:路由指令.路由服务.路由服务提供者 路由指令:ng-view ngView指令主要用于将路由指向的页面渲染到当前页面的布局中. 语法: <ng-

  • 详解angular路由高亮之RouterLinkActive

    路由高亮是什么?有什么好处? 当你在做一个后台管理系统,左边是一排路由导航,点击可以进入不同的页面,那么这个路由所在dom元素会添加上样式表示当前是位置. 但是一刷新你会发现,这个样式没了... 怎么办? 采用路由高亮:当路由被激活时允许你添加一个class在你添加路由的dom元素上,只有url变化时才会移除此样式. 当前路由被激活或者当前路由处于激活状态表示页面的url中路由和当前dom标签里的路由想匹配. // 用法概览 @Directive({ selector: '[routerLink

  • 详解PyTorch中Tensor的高阶操作

    条件选取:torch.where(condition, x, y) → Tensor 返回从 x 或 y 中选择元素的张量,取决于 condition 操作定义: 举个例子: >>> import torch >>> c = randn(2, 3) >>> c tensor([[ 0.0309, -1.5993, 0.1986], [-0.0699, -2.7813, -1.1828]]) >>> a = torch.ones(2,

  • 详解Angular之路由基础

    目录 一.路由相关对象 二.路由对象的位置 三.路由配置 四.代码中通过Router对象导航 五.配置不存在的路径 六.重定向路由 七.在路由时候传递数据 一.路由相关对象 Router和RouterLink作用一样,都是导航.Router是在Controller中用的,RouterLink是在模版中用到. 二.路由对象的位置 1.Routes对象 配置在模块中.Routes由一组配置信息组成,每个配置信息至少包含两个属性,Path和Component. 2.RouterOutlet 在模版中

  • 详解Angular中$cacheFactory缓存的使用

    最近在学习使用angular,慢慢从jquery ui转型到用ng开发,发现了很多不同点,继续学习吧: 首先创建一个服务,以便在项目中的controller中引用,服务有几种存在形式,factory();service();constant();value();provider();其中provider是最基础的,其他服务都是基于这个写的,具体区别这里就不展开了,大家可以看看源码:服务是各个controller之间通话的重要形式,在实际项目中会用的很多,下面是代码: angular.module

随机推荐