Поделиться через


Создание фиксирующих точек с модификаторами инерции

В этой статье мы подробно рассмотрим, как использовать функцию InertiaModifier отслеживателя взаимодействия для создания движений с фиксированной точкой остановки.

Предпосылки

Здесь предполагается, что вы знакомы с понятиями, описанными в следующих статьях:

Что такое точки привязки и почему они полезны?

При создании индивидуальных возможностей манипуляции иногда полезно создавать специальные точки положения , к которым InteractionTracker всегда остановится на холсте с прокруткой или увеличением. Они часто называются точками привязки.

Обратите внимание, что в следующем примере прокрутка может оставить пользовательский интерфейс в неловком положении между различными изображениями:

Прокрутка без точек привязки

При добавлении опорных точек, при остановке прокрутки между изображениями, они "прикрепляются" к указанной позиции. Благодаря точкам привязки процесс прокрутки изображений становится значительно более чистым и отзывчивым.

Прокрутка с помощью одной точки привязки

InteractionTracker и Модификаторы инерции

При создании настраиваемых взаимодействий с помощью InteractionTracker вы можете создавать эффекты движения со snap-точками, используя модификаторы инерции. Инерционные модификаторы по сути являются способом определить, где или как InteractionTracker достигает своего назначения, входя в состояние инерции. Можно применить инерционные модификаторы, чтобы повлиять на положение X или Y или свойства Scale объекта InteractionTracker.

Существует 3 типа инерционных модификаторов:

  • InteractionTrackerInertiaRestingValue — способ изменить конечное положение покоя после взаимодействия или программно заданной скорости. Предопределенное движение переместит InteractionTracker на эту позицию.
  • InteractionTrackerInertiaMotion — это способ задать определенное движение, которое InteractionTracker выполнит после взаимодействия или программной скорости. Окончательная позиция будет производной от этого движения.
  • InteractionTrackerInertiaNaturalMotion — метод определения финальной позиции покоя после взаимодействия или скорости, задаваемой программой, вместе с анимацией, основанной на законах физики (NaturalMotionAnimation).

При входе в состояние инерции InteractionTracker оценивает каждый из назначенных ему инерционных модификаторов и определяет, подходят ли какие-либо из них. Это подразумевает, что вы можете создать и назначить несколько инерционных модификаторов к трекеру взаимодействий InteractionTracker, но при определении каждого из них необходимо выполнить такие действия:

  1. Определите условие — это выражение, задающее условное выражение, когда должен применяться этот конкретный InertiaModifier. Для этого часто требуется взглянуть на NaturalRestingPosition в InteractionTracker (назначение с учетом инерции по умолчанию).
  2. Определите значение RestingValue/Motion/NaturalMotion— определите фактическое выражение значения resting, выражение движения или NaturalMotionAnimation, которое происходит при выполнении условия.

Замечание

Аспект условий модификаторов инерции оценивается только один раз, когда InteractionTracker входит в неподвижность. Однако только для InertiaMotion, выражение движения вычисляется каждый кадр для модификатора, условие которого верно.

Пример

Теперь давайте посмотрим, как можно использовать 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);