この記事では、InteractionTracker の InertiaModifier 機能を使用して、指定したポイントにスナップするモーション エクスペリエンスを作成する方法について詳しく説明します。
[前提条件]
ここでは、これらの記事で説明されている概念を理解していることを前提としています。
スナップ ポイントとは何か、またスナップポイントが役に立つのはなぜですか?
カスタム操作エクスペリエンスを構築する際、スクロールおよびズーム可能なキャンバス内に、InteractionTracker が必ず停止する特殊な位置ポイント を作成すると役立つ場合があります。 これらは、多くの場合、スナップポイント
次の例では、スクロールによって UI が異なる画像間のぎこちない位置に残される可能性があることに注意してください。
スナップポイントを追加した場合、画像間のスクロールを停止すると、指定した位置に "スナップ" されます。 スナップポイントを使用すると、画像をスクロールするエクスペリエンスがはるかにクリーンで応答性が高くなります。
InteractionTracker と InertiaModifiers
InteractionTracker を使用してカスタマイズされた操作エクスペリエンスを構築する場合は、InertiaModifiers を使用してスナップ ポイントモーション エクスペリエンスを作成できます。 InertiaModifier は基本的に、慣性状態に入ったときに InteractionTracker が宛先に到達する場所または方法を定義する方法です。 InertiaModifier を適用して、InteractionTracker の X または Y 位置またはスケール プロパティに影響を与えることができます。
InertiaModifier には、次の 3 種類があります。
- InteractionTrackerInertiaRestingValue – 対話式操作またはプログラムによる速度の後に最終的な休止位置を変更する方法です。 定義済みのモーションは、InteractionTracker をその位置に移動します。
- InteractionTrackerInertiaMotion – InteractionTracker が対話またはプログラムの速度の後に実行する特定のモーションを定義する方法です。 最後の位置はこのモーションから派生します。
- InteractionTrackerInertiaNaturalMotion – 対話式操作またはプログラムによる速度の後に、物理ベースのアニメーション (NaturalMotionAnimation) を使用して最終的な休止位置を定義する方法です。
慣性を入力すると、InteractionTracker は、割り当てられている InertiaModifier を評価し、いずれかが適用されるかどうかを判断します。 つまり、InteractionTracker に複数の InertiaModifier を作成して割り当てることができますが、それぞれを定義するときは、次の操作を行う必要があります。
- Condition を定義します。この特定の InertiaModifier を実行する必要がある場合に条件ステートメントを定義する式です。 多くの場合、InteractionTracker の NaturalRestingPosition (既定の慣性を指定した宛先) を確認する必要があります。
- RestingValue/Motion/NaturalMotion を定義する – 条件が満たされたときに行われる実際の静止値式、モーション式、または NaturalMotionAnimation を定義します。
注
InertiaModifiers の条件の側面は、InteractionTracker が慣性に入ったときに 1 回だけ評価されます。 ただし、InertiaMotion の場合にのみ、条件が true の修飾子のフレームごとにモーション式が評価されます。
例
次に、InertiaModifiers を使用してスナップ ポイント エクスペリエンスを作成し、画像のスクロール キャンバスを再作成する方法を見てみましょう。 この例では、各操作は 1 つの画像を移動することを目的としています。これは、多くの場合、単一の必須スナップポイントと呼ばれます。
まず、InteractionTracker、VisualInteractionSource、InteractionTracker の位置を利用する式を設定します。
private void SetupInput()
{
_tracker = InteractionTracker.Create(_compositor);
_tracker.MinPosition = new Vector3(0f);
_tracker.MaxPosition = new Vector3(3000f);
_source = VisualInteractionSource.Create(_root);
_source.ManipulationRedirectionMode =
VisualInteractionSourceRedirectionMode.CapableTouchpadOnly;
_source.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia;
_tracker.InteractionSources.Add(_source);
var scrollExp = _compositor.CreateExpressionAnimation("-tracker.Position.Y");
scrollExp.SetReferenceParameter("tracker", _tracker);
ElementCompositionPreview.GetElementVisual(scrollPanel).StartAnimation("Offset.Y", scrollExp);
}
次に、単一の必須スナップ ポイント動作ではコンテンツが上下に移動するため、スクロール可能なコンテンツを上に移動する 1 つと下に移動する 2 つの異なる慣性修飾子が必要になります。
// Snap-Point to move the content up
var snapUpModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
// Snap-Point to move the content down
var snapDownModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
スナップを上下にするかどうかは、InteractionTracker がスナップ距離 (スナップ位置間の距離) を基準にして自然に配置される場所に基づいて決定されます。 中間点を越える場合は、下にスナップし、それ以外の場合は上にスナップします。 (この例では、スナップ距離を PropertySet に格納します)
// Is NaturalRestingPosition less than the halfway point between Snap Points?
snapUpModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y < (this.StartingValue - " +
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapUpModifier.Condition.SetReferenceParameter("prop", _propSet);
// Is NaturalRestingPosition greater than the halfway point between Snap Points?
snapDownModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y >= (this.StartingValue - " +
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapDownModifier.Condition.SetReferenceParameter("prop", _propSet);
次の図は、発生しているロジックの視覚的な説明を示しています。
次に、InertiaModifier ごとに Resting 値を定義するだけで済みます。InteractionTracker の位置を前のスナップ位置または次のスナップ位置に移動します。
snapUpModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue - mod(this.StartingValue, prop.snapDistance)");
snapUpModifier.RestingValue.SetReferenceParameter("prop", _propSet);
snapDownModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue + prop.snapDistance - mod(this.StartingValue, " +
"prop.snapDistance)");
snapDownModifier.RestingValue.SetReferenceParameter("prop", _propSet);
最後に、InertiaModifiers を InteractionTracker に追加します。 InteractionTracker が InertiaState に入ると、InertiaModifier の条件がチェックされ、その位置が変更されるかどうかを確認します。
var modifiers = new InteractionTrackerInertiaRestingValue[] {
snapUpModifier, snapDownModifier };
_tracker.ConfigurePositionYInertiaModifiers(modifiers);