アニメーションとタイミング システムの概要
ここでは、タイミング システムで、アニメーションの Timeline および Clock の各クラスを使用してプロパティをアニメーション化する方法について説明します。
必要条件
このトピックを理解するには、「アニメーションの概要」の説明に従って、WPF アニメーションを使用し、プロパティをアニメーション化できる必要があります。 また、依存関係プロパティについても知っておくと役に立ちます。詳細については、「依存関係プロパティの概要」を参照してください。
タイムラインとクロック
「アニメーションの概要」では、Timeline で時間のセグメントを表す方法、およびアニメーションが出力値を生成する Timeline の 1 つの型であることを説明しました。 Timeline 自体は、時間のセグメントを記述する以外、何も実行しません。 実際の処理を実行するのは、タイムラインの Clock オブジェクトです。 同様に、アニメーションは実際にはプロパティをアニメーション化しません。アニメーション クラスは出力値の計算方法を記述しますが、アニメーション出力を実行し、その出力をプロパティに適用するのは、そのアニメーション用に作成された Clock です。
Clock は、Timeline のタイミングに関連する実行時の状態を維持する特殊な型のオブジェクトです。 このオブジェクトは、アニメーションおよびタイミング システムには不可欠な 3 つの情報、CurrentTime、CurrentProgress、および CurrentState を提供します。 Clock は、その現在の時刻、進行状況、および状態を、その Timeline で記述された、Duration、RepeatBehavior、AutoReverse などのタイミング動作を使用して判断します。
ほとんどの場合、タイムラインに自動的に Clock が作成されます。 Storyboard メソッドや BeginAnimation メソッドを使用してアニメーション化すると、タイムラインとアニメーションに自動的にクロックが作成されて対象のプロパティに適用されます。 Timeline の CreateClock メソッドを使用して、Clock を明示的に作成することもできます。 MediaTimeline.CreateClock メソッドは、それが呼び出された Timeline に対応する型のクロックを作成します。 Timeline に子タイムラインが含まれる場合、それらの子タイムラインの Clock オブジェクトも作成されます。 結果として得られる Clock オブジェクトは、クロック オブジェクトを作成した Timeline オブジェクト ツリーと同じ構造のツリーに配置されます。
さまざまな型のタイムラインに対応するさまざまな型のクロックが存在します。 いくつかの Timeline 型とそれに対応する Clock 型を次の表に示します。
タイムラインの型 |
クロックの型 |
クロックの目的 |
---|---|---|
Animation (AnimationTimeline から継承) |
依存関係プロパティの出力値を生成します。 |
|
メディア ファイルを処理します。 |
||
その子 Clock オブジェクトをグループ化し、制御します。 |
||
その子 Clock オブジェクトをグループ化し、制御します。 |
作成した AnimationClock オブジェクトはすべて、ApplyAnimationClock メソッドを使用して互換性のある依存関係プロパティに適用できます。
同じようなオブジェクトを多数アニメーション化するなど、パフォーマンスに大きな負荷がかかるシナリオでは、独自の Clock を管理することによってパフォーマンスを向上できます。
クロックとタイム マネージャー
WPF でオブジェクトをアニメーション化する場合、タイムラインに対して作成された Clock オブジェクトはタイム マネージャーが管理します。 タイム マネージャーは、Clock オブジェクトのツリーのルートであり、そのツリーの時間のフローを制御します。 タイム マネージャーは、WPF アプリケーションごとに自動的に作成され、アプリケーション開発者には表示されません。タイム マネージャーは、1 秒に何度も "タイマーを刻み" ます。1 秒あたりのタイマー刻みの実際の回数は、使用可能なシステム リソースに応じて変わります。 これらの 1 回のタイマー刻みの間、タイム マネージャーは、タイミング ツリー内のすべての Active Clock オブジェクトの状態を計算します。
タイム マネージャー、AnimationClock、およびアニメーション化された依存関係プロパティの関係を次の図に示します。
プロパティのアニメーション化
タイムマネージャーは、タイマーを刻むときに、アプリケーション内のすべての Active Clock の時間を更新します。 Clock が AnimationClock の場合、クロックは、その作成元の AnimationTimeline の GetCurrentValue メソッドを使用して現在の出力値を計算します。 AnimationClock は、現在のローカル時刻、入力値 (通常はプロパティの基本値)、および既定の終点の値を指定した AnimationTimeline を提供します。 GetValue メソッドまたはその CLR アクセサーを使用してアニメーション化プロパティの値を取得するときに、その AnimationClock の出力を取得します。
クロック グループ
前のセクションでは、さまざまな型のタイムラインに対応するさまざまな型の Clock オブジェクトを説明しました。 タイム マネージャー、ClockGroup、AnimationClock、およびアニメーション化された依存関係プロパティの関係を次の図に示します。 アニメーションおよび他のタイムラインをグループ化する Storyboard クラスなど、他のタイムラインをグループ化するタイムラインに対して、ClockGroup が作成されます。
ClockGroup
構成
複数のクロックを単一のプロパティに関連付けることが可能です。この場合、各クロックは前のクロックの出力値をその基本値として使用します。 同じプロパティに適用された 3 つの AnimationClock オブジェクトを次の図に示します。 Clock1 は、アニメーション化されたプロパティの基本値をその入力として使用して出力を生成します。 Clock2 は、Clock1 からの出力をその入力として取得し、それを使用して出力を生成します。 Clock3 は、Clock2 からの出力をその入力として取得し、それを使用して出力を生成します。 複数のクロックが同じプロパティに同時に影響を与える場合、それらは構成チェーン内にあるものと見みなされます。
構成チェーン
構成チェーン内の AnimationClock オブジェクトの入力および出力間の関係は作成されますが、それらのタイミング動作は影響を受けません。Clock オブジェクト (AnimationClock オブジェクトを含む) は、その親 Clock オブジェクトに対して階層型の依存関係を持ちます。
複数のクロックを同じプロパティに適用するには、Storyboard、アニメーション、または AnimationClock の適用時に Compose HandoffBehavior を使用します。
タイマー刻みとイベントの統合
出力値の計算に加え、タイム マネージャーはタイマーを刻むごとに他の作業も行います。タイム マネージャーは、各クロックの状態を確認し、必要に応じてイベントを発生させます。
タイマー刻みが頻繁に発生している間は、タイマー刻みの間隔に多くのことが行われる可能性があります。 たとえば、Clock が停止してから開始し、もう一度停止する可能性あります。この場合、クロックの CurrentState 値は 3 回変更されています。 理論的には、CurrentStateInvalidated イベントは 1 回のタイマー刻みで複数回発生することは可能ですが、タイミング エンジンはイベントを統合して、CurrentStateInvalidated イベントが 1 回のタイマー刻みにつき多くても 1 回だけ発生するようにします。 これはすべてのタイミング イベントに該当します。特定の 1 Clock オブジェクトに対して、各型のイベントは 1 回だけ発生します。
タイマー刻み間隔に、Clock の状態が切り替わり、元の状態に戻った場合 (Active から Stopped に切り替わり、Active に戻る場合など) でも、関連のイベントは発生します。
タイミング イベントの詳細については、「タイミング イベントの概要」を参照してください。
プロパティの現在値と基本値
アニメーション化可能なプロパティは、基本値と現在値の 2 つの値を持つことができます。 その CLR アクセサーまたは SetValue メソッドを使用してプロパティを設定する場合は、その基本値を設定します。 プロパティをアニメーション化しない場合、その基本値と現在値は同じになります。
プロパティをアニメーション化する場合、AnimationClock はプロパティの現在値を設定します。 AnimationClock が Active または Filling の場合、プロパティの値をその CLR アクセサーまたは GetValue メソッドをとおして取得すると、AnimationClock の出力が返されます。 プロパティの基本値は、GetAnimationBaseValue メソッドを使用して取得できます。