適切に設計されたアニメーションは、アプリケーションをより楽しく、分かりやすく使用できるようにしますが、単なる装飾ではありません。
アニメーションは、いくつかの方法でアプリケーションとユーザー体験を向上させることができます。
アニメーションがないと、ウェブページの遷移は突然で不快に感じられることがあります
モーションはユーザー体験を大幅に向上させるため、アニメーションはユーザーが自分のアクションに対するアプリケーションの応答を検出する機会を与えます
優れたアニメーションは、ワークフロー全体でユーザーの注意をスムーズに誘導できます
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は、削除される要素の_子孫_の要素にある場合はアニメーションしません 。これは、親ノードが削除されると、サブツリー全体が一緒に削除され、その親ノードにアニメーションがないため、即座に削除されるためです。これは、animate.leaveでアニメーション化する要素がないことを意味します。animate.leaveの使用においてこのことを考慮する必要があります。
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 No Animation Example</ h2 > < button type = "button" class = "toggle-btn" (click) = "toggle()" >Toggle Element</ button > @if ( isShown ()) { <!-- the child node with `animate.leave` will not animate out because the parent node removal happens first and will take the child dom tree with it. --> < div class = "leave-parent" > < 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を使った複雑なアニメーション
ルート遷移アニメーション