適切に設計されたアニメーションは、アプリケーションをより楽しく、分かりやすく使用できるようにしますが、単なる装飾ではありません。 アニメーションは、いくつかの方法でアプリケーションとユーザー体験を向上させることができます。
- アニメーションがないと、ウェブページの遷移は突然で不快に感じられることがあります
- モーションはユーザー体験を大幅に向上させるため、アニメーションはユーザーが自分のアクションに対するアプリケーションの応答を検出する機会を与えます
- 優れたアニメーションは、ワークフロー全体でユーザーの注意をスムーズに誘導できます
Angularは、アプリケーションの要素をアニメーション化するためにanimate.enter
とanimate.leave
を提供します。これら2つの機能は、適切なタイミングでenterおよびleaveのCSSクラスを適用するか、サードパーティライブラリからアニメーションを適用する関数を呼び出します。animate.enter
とanimate.leave
はディレクティブではありません。これらはAngularコンパイラによって直接サポートされる特別なAPIです。これらは要素に直接使用できるほか、ホストバインディングとしても使用できます。
animate.enter
animate.enter
はDOMに_入る_要素をアニメーション化するために使用できます。CSSクラスと、transformまたはキーフレームアニメーションのいずれかを使用して、enterアニメーションを定義できます。
src/app/enter.ts
import {Component, signal} from '@angular/core';@Component({ selector: 'app-enter', templateUrl: 'enter.html', styleUrls: ['enter.css'],})export class Enter { isShown = signal(false); toggle() { this.isShown.update((isShown) => !isShown); }}
src/app/enter.html
<h2><code>animate.enter</code> Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="enter-container" animate.enter="enter-animation"> <p>The box is entering.</p> </div>}
src/app/enter.css
:host { display: block; height: 200px;}.enter-container { border: 1px solid #dddddd; margin-top: 1em; padding: 20px 20px 0px 20px; font-weight: bold; font-size: 20px;}.enter-animation { animation: slide-fade 1s;}@keyframes slide-fade { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); }}
アニメーションが完了すると、Angularはanimate.enter
で指定したクラスをDOMから削除します。アニメーションクラスは、アニメーションがアクティブな間のみ存在します。
NOTE: 要素で複数のキーフレームアニメーションまたはtransitionプロパティを使用している場合、Angularは最も長いアニメーションが完了した_後にのみ_すべてのクラスを削除します。
animate.enter
は、制御フローや動的式など、他のAngular機能と組み合わせて使用できます。animate.enter
は、単一のクラス文字列(複数のクラスがスペースで区切られているもの)またはクラス文字列の配列を受け入れます。
src/app/enter-binding.ts
import {Component, signal} from '@angular/core';@Component({ selector: 'app-enter-binding', templateUrl: 'enter-binding.html', styleUrls: ['enter-binding.css'],})export class EnterBinding { isShown = signal(false); toggle() { this.isShown.update((isShown) => !isShown); } enterClass = signal('enter-animation');}
src/app/enter-binding.html
<h2><code>animate.enter</code> Binding Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="enter-container" [animate.enter]="enterClass()"> <p>The box is entering.</p> </div>}
src/app/enter-binding.css
:host { display: block; height: 200px;}.enter-container { border: 1px solid #dddddd; margin-top: 1em; padding: 20px 20px 0px 20px; font-weight: bold; font-size: 20px;}.enter-animation { animation: slide-fade 1s;}@keyframes slide-fade { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); }}
animate.leave
animate.leave
を使用して、要素がDOMから_離れる_ときにアニメーションを適用できます。CSSクラスと、transformまたはキーフレームアニメーションのいずれかを使用して、離脱アニメーションを定義できます。
src/app/leave.ts
import {Component, signal} from '@angular/core';@Component({ selector: 'app-leave', templateUrl: 'leave.html', styleUrls: ['leave.css'],})export class Leave { isShown = signal(false); toggle() { this.isShown.update((isShown) => !isShown); }}
src/app/leave.html
<h2><code>animate.leave</code> Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="leave-container" animate.leave="leaving"> <p>Goodbye</p> </div>}
src/app/leave.css
:host { display: block; height: 200px;}.leave-container { border: 1px solid #dddddd; margin-top: 1em; padding: 20px 20px 0px 20px; font-weight: bold; font-size: 20px; opacity: 1; transition: opacity 200ms ease-in; @starting-style { opacity: 0; }}.leaving { opacity: 0; transform: translateY(20px); transition: opacity 500ms ease-out, transform 500ms ease-out;}
アニメーションが完了すると、Angularはアニメーション化された要素をDOMから自動的に削除します。
NOTE: 要素に複数のキーフレームアニメーションまたはtransitionプロパティを使用する場合、Angularはそれらのアニメーションの中で最も長いものが完了した_後にのみ_要素を削除します。
animate.leave
はsignalsやその他のbindingでも使用できます。animate.leave
は単一のクラスまたは複数のクラスで使用できます。スペースで区切られた単純な文字列として指定するか、文字列配列として指定します。
src/app/leave-binding.ts
import {Component, signal} from '@angular/core';@Component({ selector: 'app-leave-binding', templateUrl: 'leave-binding.html', styleUrls: ['leave-binding.css'],})export class LeaveBinding { isShown = signal(false); toggle() { this.isShown.update((isShown) => !isShown); } farewell = signal('leaving');}
src/app/leave-binding.html
<h2><code>animate.leave</code> Binding Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="leave-container" [animate.leave]="farewell()"> <p>Goodbye</p> </div>}
src/app/leave-binding.css
:host { display: block; height: 200px;}.leave-container { border: 1px solid #dddddd; margin-top: 1em; padding: 20px 20px 0px 20px; font-weight: bold; font-size: 20px; opacity: 1; transition: opacity 200ms ease-in; @starting-style { opacity: 0; }}.leaving { opacity: 0; transform: translateY(20px); transition: opacity 500ms ease-out, transform 500ms ease-out;}
イベントバインディング、関数、およびサードパーティライブラリ
animate.enter
とanimate.leave
はどちらも、関数呼び出しを可能にするイベントバインディング構文をサポートしています。この構文を使用して、コンポーネントコード内の関数を呼び出したり、GSAP、anime.jsなどのサードパーティのアニメーションライブラリ、またはその他のJavaScriptアニメーションライブラリを利用したり可能です。
src/app/leave-event.ts
import {AnimationCallbackEvent, Component, signal} from '@angular/core';@Component({ selector: 'app-leave-binding', templateUrl: 'leave-event.html', styleUrls: ['leave-event.css'],})export class LeaveEvent { isShown = signal(false); toggle() { this.isShown.update((isShown) => !isShown); } leavingFn(event: AnimationCallbackEvent) { // Example of calling GSAP // gsap.to(event.target, { // duration: 1, // x: 100, // // arrow functions are handy for concise callbacks // onComplete: () => event.animationComplete() // }); event.animationComplete(); }}
src/app/leave-event.html
<h2><code>animate.leave</code> Function Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="leave-container" (animate.leave)="leavingFn($event)"> <p>Goodbye</p> </div>}
src/app/leave-event.css
:host { display: block; height: 200px;}.leave-container { border: 1px solid #dddddd; margin-top: 1em; padding: 20px 20px 0px 20px; font-weight: bold; font-size: 20px; opacity: 1; transition: opacity 200ms ease-in; @starting-style { opacity: 0; }}.leaving { opacity: 0; transform: translateY(20px); transition: opacity 500ms ease-out, transform 500ms ease-out;}
$event
オブジェクトはAnimationCallbackEvent
型です。これにはtarget
として要素が含まれ、アニメーションが終了したときにフレームワークに通知するためのanimationComplete()
関数を提供します。
IMPORTANT: Angularが要素を削除するためには、animate.leave
を使用する際にanimationComplete()
関数を必ず呼び出す必要があります。
animate.leave
を使用する際にanimationComplete()
を呼び出さない場合、Angularは4秒の遅延後に自動的にその関数を呼び出します。遅延の期間は、MAX_ANIMATION_TIMEOUT
トークンをミリ秒単位で提供することにより設定できます。
{ provide: MAX_ANIMATION_TIMEOUT, useValue: 6000 }
テスト
TestBedは、テスト環境でアニメーションを有効または無効にするための組み込みサポートを提供します。CSSアニメーションはブラウザでの実行が必要であり、多くのAPIはテスト環境では利用できません。デフォルトでは、TestBedはテスト環境でアニメーションを無効にします。
ブラウザテスト、例えばエンドツーエンドテストでアニメーションが動作していることをテストしたい場合は、テスト設定でanimationsEnabled: true
を指定することで、TestBedをアニメーションを有効にするように設定できます。
TestBed.configureTestingModule({animationsEnabled: true});
これにより、テスト環境でのアニメーションが通常通りに動作するように設定されます。
NOTE: 一部のテスト環境では、animationstart
、animationend
のようなアニメーションイベントや、それらに相当するトランジションイベントを発行しません。