在本文中,我们将更深入地探讨如何使用 InteractionTracker 的惯性修改器功能来创建贴靠到指定点的运动体验。
先决条件
此处,我们假设你熟悉以下文章中讨论的概念:
什么是捕捉点,为什么它们很有用?
在创建自定义操作体验时, 有时在可滚动/可缩放画布中创建专用的 位置点 会很有帮助,以便 InteractionTracker 最终能够停留于这些点上。 这些通常称为 吸附点。
请注意,在以下示例中,滚动如何使 UI 处于不同图像之间的尴尬位置:
如果添加贴靠点,那么在停止滚动图像时,它们会快速贴合到指定的位置。 借助贴靠点,它使滚动浏览图像的体验更加清晰且响应更快速。
InteractionTracker 和 InertiaModifiers
在使用 InteractionTracker 构建自定义操作体验时,可以通过利用惯性修饰器来创建贴靠点运动体验。 InertiaModifiers 本质上是一种方法,用于定义 InteractionTracker 在进入惯性状态时到达其目的地的位置或方式。 可以应用 InertiaModifiers 来影响 InteractionTracker 的 X 或 Y 位置或缩放属性。
有 3 种类型的 InertiaModifiers:
- InteractionTrackerInertiaRestingValue – 一种用于在交互或程序速度之后调整最终静止位置的机制。 预定义的动作会将 InteractionTracker 带到该位置。
- InteractionTrackerInertiaMotion – 定义 InteractionTracker 在交互或编程速度之后执行的特定运动的方法。 最终位置将通过此运动得出。
- InteractionTrackerInertiaNaturalMotion – 定义交互或编程速度之后的最终静止位置的机制, 并带有基于物理的动画(NaturalMotionAnimation)。
进入惯性时,InteractionTracker 会评估与其关联的每个惯性修饰符,并确定它们是否适用。 这意味着你可以创建多个 InertiaModifiers 并分配给 InteractionTracker,但是,在定义每个对象时,需要执行以下步骤:
- 定义条件 – 一个表达式,用于定义此特定 InertiaModifier 的执行条件。 这通常需要查看 InteractionTracker 的 NaturalRestingPosition(给定默认惯性的目标)。
- 定义静止值/动作/自然运动 – 定义满足条件时实际应用的静止值表达式、动作表达式或自然运动动画。
注释
当 InteractionTracker 进入惯性状态时,InertiaModifiers 的条件因素仅被评估一次。 但是,这仅适用于 InertiaMotion,此时运动表达式会对条件为 true 的修饰符每帧进行评估。
示例:
现在让我们看看如何使用 InertiaModifiers 创建一些对齐点体验来重新创建图像滚动画布。 在此示例中,每个操作都旨在可能移动单个图像 - 这通常称为“单个必需对齐点”。
首先,我们从初始化 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);
}
接下来,由于单一强制对齐点行为会将内容向上或向下移动,因此需要两个不同的惯性修饰符:一个将滚动内容向上移动,另一个将其向下移动。
// 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 定义静止值:将 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 进入惯性状态时,它将检查惯性修饰符的条件,以确定其位置是否需要修改。
var modifiers = new InteractionTrackerInertiaRestingValue[] {
snapUpModifier, snapDownModifier };
_tracker.ConfigurePositionYInertiaModifiers(modifiers);