动画

Angular动画实现了一套能跟纯CSS动画性能相媲美的类库,而对于浏览器而言是基于原生 Web Animations API 接口实现的,所以如果有浏览器上兼容问题,还需要引入 web-animations.min.js

总之,很牛B。

一、引入模块

动画模块只允许导入一次,所以最好在根模块 app.module.ts 中导入它。

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
    imports: [ BrowserModule, BrowserAnimationsModule ]
});

然后可以组件导入相关动画常用类:

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

二、使用动画

假定我们定义好一个动画后,是如何呈现的呢?很简单采用 @ 加动画触发器名称。

<div [@ant]="antStatus"></div>

表达式左边为 [@ant] 为动画触发器名称;右边绑定一个变量,这样我们可以通过组件类变更变量的值,从而实现切换不同动画状态。

class TestComponent {
    antStatus: string = 'normal';

    toggle() {
        this.antStatus = this.antStatus ===  'normal' ? 'end' : 'normal';
    }
}

那么,我们是如何定义这个动画触发器的呢?

三、定义动画

@Component 装饰器有个 animations 动画属性,跟动画有关的都放在这里。

下面是一个简单的示例:

@Component({
    animations: [
        trigger('ant', [
            state('normal', style({ transform: 'scale(1)' })),
            state('big', style({ transform: 'scale(2)' })),
            transition('normal => big', animate('500ms ease-in')),
            transition('big => *', animate('500ms ease-out')),
            transition(':enter', [
                style({ transform: 'translateX(-100%)' }),
                animate(500)
            ]),
            transition(':leave', [
                group([
                    animate('0.2s ease', style({
                        transform: 'translate(150px,25px)'
                    })),
                    animate('0.5s 0.2s ease', style({
                        opacity: 0
                    }))
                ])
            ])
        ])
    ]
})

Angular提供一套动画DSL,但为数并不多。利用 trigger 定义一个动画触发器,并为其取名:itemAnim。它接收的是一个数组,可以在数组内定义状态(state)、转场(transition)信息。

  • state 状态定义很简单,名称以及CSS样式对象。
  • transition 状态转场。

对于动画状态的定义,有多种类型:

  • style CSS样式对象。
  • animate 动画效果。
    • keyframes 定义 @keyframes 规则

当然,动画也是有执行顺序的:

  • sequence 按顺序执行动画。
  • group 按同步执行动画。
  • stagger 动画交错处理。

有时,希望整个动画里对某个元素增加额外的动画时:

  • query 指定某个状态下某个元素的动画状态。
  • animateChild 指当存在父子动画时,子动画会变无效,需要使用此属性强制触发。

转场

所谓转场是指从一种状态到另一种状态的过程,并且用 => 来表示方向。比如,从 normal 状态到 big 状态。

transition('normal => big');

别名

transition 转场提供了三个别名,使动画处理更便利。

  • :enter 进场时。
  • :leave 离场时。
  • * 任何状态。

四、路由动画

我想在移动端做路由转场动画一定非常酷吧,好在Angular4以后就内置了路由动画切换。

1、定义转场动画效果

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

export function routerTransition() {
    return slideToRight();
}

// 右向左滑动
function slideToRight() {
    return trigger('routerTransition', [
        state('void', style({ position: 'fixed', width: '100%' })),
        state('*', style({ position: 'fixed', width: '100%' })),
        transition(':enter', [
            style({ transform: 'translateX(-100%)' }),
            animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
        ]),
        transition(':leave', [
            style({ transform: 'translateX(0%)' }),
            animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))
        ])
    ]);
}

由于会在多个组件中应用,所以将动画封装成独立类,这样不必重复写动画代码。

2、设定动画

在每一个需要路由动画的组件里设定动画效果。

import { routerTransition } from "router.animations";

@Component({
    selector: 'about',
    template: `<div style="width:100%;height: 300px; background:#f00;"></div>`,
    animations: [routerTransition()],
    host: { '[@routerTransition]': '' }
})
export class AboutComponent {
}

这里 host 请看 host 章节。

3、运行效果

路由转场
1.5.7.1 - 路由转场

结论

Angular动画性能真的非常牛B,可以和原生相比。

而动画的难点,我认为还是在于这一套DSL语言的灵活运用。不过并不难,很多都是我们日常在CSS中使用到的名词。

results matching ""

    No results matching ""