適切に設計されたアニメーションは、アプリケーションをより楽しく、分かりやすく使用できるようにしますが、単なる装飾ではありません。
アニメーションは、いくつかの方法でアプリケーションとユーザー体験を向上させることができます。
アニメーションがないと、ウェブページの遷移は突然で不快に感じられることがあります
モーションはユーザー体験を大幅に向上させるため、アニメーションはユーザーが自分のアクションに対するアプリケーションの応答を検出する機会を与えます
優れたアニメーションは、ワークフロー全体でユーザーの注意をスムーズに誘導できます
Angularは、アプリケーションの要素をアニメーション化するためにanimate.enterとanimate.leaveを提供します。これら2つの機能は、適切なタイミングでenterおよびleaveのCSSクラスを適用するか、サードパーティライブラリからアニメーションを適用する関数を呼び出します。animate.enterとanimate.leaveはディレクティブではありません。これらはAngularコンパイラによって直接サポートされる特別なAPIです。これらは要素に直接使用できるほか、ホストバインディングとしても使用できます。
animate.enterはDOMに_入る_要素をアニメーション化するために使用できます。CSSクラスと、transitionまたはキーフレームアニメーションのいずれかを使用して、enterアニメーションを定義できます。
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);
}
}
< h2 >< code >animate.enter</ code > Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "enter-container" animate.enter = "enter-animation" >
< p >The box is entering.</ p >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.enter-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
}
.enter-container p {
margin : 0 ;
}
.enter-animation {
animation : slide-fade 1 s ;
}
@keyframes slide-fade {
from {
opacity : 0 ;
transform : translateY ( 20 px );
}
to {
opacity : 1 ;
transform : translateY ( 0 );
}
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
アニメーションが完了すると、Angularはanimate.enterで指定したクラスをDOMから削除します。アニメーションクラスは、アニメーションがアクティブな間のみ存在します。
NOTE: 要素で複数のキーフレームアニメーションまたはtransitionプロパティを使用している場合、Angularは最も長いアニメーションが完了した_後にのみ_すべてのクラスを削除します。
animate.enterは、制御フローや動的式など、他のAngular機能と組み合わせて使用できます。animate.enterは、単一のクラス文字列(複数のクラスがスペースで区切られているもの)またはクラス文字列の配列を受け入れます。
CSSトランジションの使用についての簡単な注意:キーフレームアニメーションの代わりにトランジションを使用することを選択した場合、animate.enterで要素に追加されるクラスは、トランジションがアニメーション_する先の_状態を表します。基本要素のCSSは、アニメーションが実行されないときの要素の外観であり、CSSトランジションの終了状態に似ている可能性があります。そのため、トランジションが機能するために適切な_from_状態を持つために、@starting-styleと組み合わせる必要があります。
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' );
}
< h2 >< code >animate.enter</ code > Binding Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "enter-container" [animate.enter] = "enterClass()" >
< p >The box is entering.</ p >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.enter-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
}
.enter-container p {
margin : 0 ;
}
.enter-animation {
animation : slide-fade 1 s ;
}
@keyframes slide-fade {
from {
opacity : 0 ;
transform : translateY ( 20 px );
}
to {
opacity : 1 ;
transform : translateY ( 0 );
}
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
animate.leave を使用して、要素がDOMから_離れる_ときにアニメーションを適用できます。CSSクラスと、transformまたはキーフレームアニメーションのいずれかを使用して、離脱アニメーションを定義できます。
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);
}
}
< h2 >< code >animate.leave</ code > Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "leave-container" animate.leave = "leaving" >
< p >Goodbye</ p >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.leave-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
opacity : 1 ;
transition : opacity 200 ms ease-in ;
@ starting-style {
opacity : 0 ;
}
}
.leave-container p {
margin : 0 ;
}
.leaving {
opacity : 0 ;
transform : translateY ( 20 px );
transition :
opacity 500 ms ease-out ,
transform 500 ms ease-out ;
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
アニメーションが完了すると、Angularはアニメーション化された要素をDOMから自動的に削除します。
NOTE: 要素に複数のキーフレームアニメーションまたはtransitionプロパティを使用する場合、Angularはそれらのアニメーションの中で最も長いものが完了した_後にのみ_要素を削除します。
animate.leave はsignalsやその他のbindingでも使用できます。animate.leave は単一のクラスまたは複数のクラスで使用できます。スペースで区切られた単純な文字列として指定するか、文字列配列として指定します。
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' );
}
< h2 >< code >animate.leave</ code > Binding Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "leave-container" [animate.leave] = "farewell()" >
< p >Goodbye</ p >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.leave-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
opacity : 1 ;
transition : opacity 200 ms ease-in ;
@ starting-style {
opacity : 0 ;
}
}
.leave-container p {
margin : 0 ;
}
.leaving {
opacity : 0 ;
transform : translateY ( 20 px );
transition :
opacity 500 ms ease-out ,
transform 500 ms ease-out ;
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
animate.leaveアニメーションの実行方法とアニメーションが発生するタイミングには、いくつかの微妙な点があります。animate.leaveは、削除される要素に配置されている場合に機能します。また、animate.leaveが削除される要素の_子孫_要素に配置されている場合、それらの子アニメーションは親ノードがDOMから削除される_前に_実行されます。これにより、親ノードが早期に消えることなく、子要素を確実にアニメーションで退場させることができます。
import { Component , signal } from '@angular/core' ;
@ Component ({
selector: 'app-leave-parent' ,
templateUrl: 'leave-parent.html' ,
styleUrls: [ 'leave-parent.css' ],
})
export class LeaveParent {
isShown = signal ( false );
toggle () {
this .isShown. update (( isShown ) => ! isShown);
}
}
< h2 >< code >animate.leave</ code > Parent Sub-tree Animation Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "leave-parent" >
<!-- the child node with `animate.leave` will animate first
before the parent node is removed from the DOM. -->
< div class = "leave-container" animate.leave = "leaving" >
< p >Goodbye</ p >
</ div >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.leave-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
opacity : 1 ;
transition : opacity 200 ms ease-in ;
@ starting-style {
opacity : 0 ;
}
}
.leave-container p {
margin : 0 ;
}
.leaving {
opacity : 0 ;
transform : translateY ( 20 px );
transition :
opacity 500 ms ease-out ,
transform 500 ms ease-out ;
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
animate.enterとanimate.leaveはどちらも、関数呼び出しを可能にするイベントバインディング構文をサポートしています。この構文を使用して、コンポーネントコード内の関数を呼び出したり、GSAP 、anime.js などのサードパーティのアニメーションライブラリ、またはその他のJavaScriptアニメーションライブラリを利用したり可能です。
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 ();
}
}
< h2 >< code >animate.leave</ code > Function Example</ h2 >
< button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button >
@if ( isShown ()) {
< div class = "leave-container" (animate.leave) = "leavingFn($event)" >
< p >Goodbye</ p >
</ div >
}
:host {
display : block ;
height : 200 px ;
}
.leave-container {
border : 1 px solid #dddddd ;
margin-top : 1 em ;
padding : 20 px ;
font-weight : bold ;
font-size : 20 px ;
opacity : 1 ;
transition : opacity 200 ms ease-in ;
@ starting-style {
opacity : 0 ;
}
}
.leave-container p {
margin : 0 ;
}
.leaving {
opacity : 0 ;
transform : translateY ( 20 px );
transition :
opacity 500 ms ease-out ,
transform 500 ms ease-out ;
}
.toggle-btn {
background : transparent ;
border : 1 px solid var ( --primary-contrast , black );
color : var ( --primary-contrast , black );
padding : 10 px 24 px ;
border-radius : 8 px ;
cursor : pointer ;
}
$eventオブジェクトはAnimationCallbackEvent 型です。これにはtargetとして要素が含まれ、アニメーションが終了したときにフレームワークに通知するためのanimationComplete()関数を提供します。
IMPORTANT: Angularが要素を削除するためには、animate.leaveを使用する際にanimationComplete()関数を必ず 呼び出す必要があります。
animate.leaveを使用する際にanimationComplete()を呼び出さない場合、Angularは4秒の遅延後に自動的にその関数を呼び出します。遅延の期間は、MAX_ANIMATION_TIMEOUT トークンをミリ秒単位で提供することにより設定できます。
同じコンポーネント内でレガシーアニメーションとanimate.enterおよびanimate.leaveを一緒に使用できません。そうすると、enterクラスが要素に残ったり、leavingノードが削除されなかったりします。それ以外では、同じ_アプリケーション_内でレガシーアニメーションと新しいanimate.enterおよびanimate.leaveアニメーションの両方を使用することは問題ありません。唯一の注意点はコンテンツプロジェクションです。レガシーアニメーションを持つコンポーネントからanimate.enterまたはanimate.leaveを持つ別のコンポーネントにコンテンツをプロジェクトする場合、またはその逆の場合、これは同じコンポーネント内で一緒に使用した場合と同じ動作になります。これはサポートされていません。
TestBedは、テスト環境でアニメーションを有効または無効にするための組み込みサポートを提供します。CSSアニメーションはブラウザでの実行が必要であり、多くのAPIはテスト環境では利用できません。デフォルトでは、TestBedはテスト環境でアニメーションを無効にします。
ブラウザテスト、例えばエンドツーエンドテストでアニメーションが動作していることをテストしたい場合は、テスト設定でanimationsEnabled: trueを指定することで、TestBedをアニメーションを有効にするように設定できます。
TestBed . configureTestingModule ({animationsEnabled: true });
これにより、テスト環境でのアニメーションが通常通りに動作するように設定されます。
NOTE: 一部のテスト環境では、animationstart、animationendのようなアニメーションイベントや、それらに相当するトランジションイベントを発行しません。
以下の項目にも興味があるかもしれません:
CSSを使った複雑なアニメーション
ルート遷移アニメーション