Angular2のアニメーション Tips
基本的な技術は公式チュートリアルを参照すれば大体把握出来るので、
変則的な技術を書いていきます。
Angular2のバージョンを2.2.0で記載していきます。
※https://angular.io/docs/ts/latest/guide/animations.html
アジェンダ
- 単純なアニメーション
- ちょっとめんどくさいアニメーション
単純なアニメーション
下記コードの実装では「次へ」と「前へ」を交互にクリックしないと「Anime」の文字列が移動しません。
理由としましては連続して同じ要素をクリックしてもAnimeComponentクラスのstatusフィールドが変化した事には
ならず、変更検知のトリガが実行されないからです。
対象方法としては下記の「ちょっとめんどくさいアニメーション」項目を読んで頂ければと思います。
import { Component, trigger, state, style, transition, animate } from '@angular/core';
@Component({
selector: 'anime-block',
animations:[
trigger('buttomstate', [
state('void', style({
backgroundColor: '#eee',
transform: 'translateX(200px)'
})),
state('next', style({
backgroundColor: '#eee',
transform: 'translateX(0px)'
})),
state('prev', style({
backgroundColor: '#eee',
transform: 'translateX(-100px)'
})),
transition('* => next', animate(500, style({transform: 'translateX(0px)'}))),
transition('* => prev', animate(500, style({transform: 'translateX(-100px)'})))
])
],
template: `
<h1 [@buttomstate]="status">{{name}}</h1>
<div (click)="onClick('next')">次へ</div>
<div (click)="onClick('prev')">前へ</div>
`,
})
export class AnimeComponent
{
public name:string = 'Anime';
public status:string = 'void';
public onClick(status: string)
{
switch(status)
{
case 'next':
this.status = 'next';
break;
case 'prev':
this.status = 'prev';
break;
}
}
}
ちょっとめんどくさいアニメーション
「単純なアニメーション」項目では同じ要素を連続でクリックしても「Anime」が移動しませんでした。
今回は連続で要素をクリックした際に移動をさせる処理を下記コードに実装してみました。
追加したコードはアニメーションが実行完了した際に呼び出されるイベントハンドラになります。
アニメーションが完了した際にイベントハンドラ内でstatusフィールドを「next」「prev」でもない
第三の文字列にする事により変更検知に引っ掛けるという物になります。
既存Bugの問題でアニメーション完了のイベントハンドラ内でstatusフィールドを変更しても変更検知に
引っかからないという問題が存在していました。※https://github.com/angular/angular/issues/11881
なので対処として非同期処理を同期処理のように無理矢理実行するようにして変更検知するようにしました。
import { Component, NgZone, trigger, state, style, transition, animate, AnimationTransitionEvent } from '@angular/core';
@Component({
selector: 'anime-block',
animations:[
trigger('buttomstate', [
state('void', style({
backgroundColor: '#eee',
transform: 'translateX(200px)'
})),
state('next', style({
backgroundColor: '#eee',
transform: 'translateX(0px)'
})),
state('prev', style({
backgroundColor: '#eee',
transform: 'translateX(-100px)'
})),
transition('* => next', animate(500, style({transform: 'translateX(0px)'}))),
transition('* => prev', animate(500, style({transform: 'translateX(-100px)'})))
])
],
template: `
<h1 [@buttomstate]="status" (@buttomstate.done)="animationDone($event)">{{name}}</h1>
<div (click)="onClick('next')">次へ</div>
<div (click)="onClick('prev')">前へ</div>
`,
})
export class AnimeComponent
{
public name:string = 'Anime';
public status:string = 'void';
public constructor(private zone:NgZone){}
public onClick(status: string)
{
if(this.status != 'void')
{
return;
}
switch(status)
{
case 'next':
this.status = 'next';
break;
case 'prev':
this.status = 'prev';
break;
}
}
public animationDone(event:AnimationTransitionEvent)
{
this.zone.run(() => {
if(event.toState == 'void')
{
return;
}
this.status = 'void';
});
}
}
サンプルコードのリポジトリ
※https://github.com/MakotoTaniguchi/Sample_Angular2/tree/ver_2.0