Compartir a través de


Creación de puntos de acoplamiento con modificadores de inercia

En este artículo, se profundiza en cómo usar la característica InteractionTracker InertiaModifier para crear experiencias de movimiento que se ajusten a un punto especificado.

Requisitos previos

En este caso, se supone que está familiarizado con los conceptos descritos en estos artículos:

¿Qué son los puntos de acoplamiento y por qué son útiles?

Al crear experiencias de manipulación personalizadas, a veces resulta útil crear puntos de posición especializados dentro del lienzo desplazable o zoomable en el que InteractionTracker siempre descansará. A menudo se denominan puntos de acoplamiento.

Observe en el ejemplo siguiente cómo el desplazamiento puede dejar la interfaz de usuario en una posición torpe entre las distintas imágenes:

Desplazamiento sin puntos de acoplamiento

Si agrega puntos de acoplamiento, al dejar de desplazarse entre las imágenes, se "acoplan" a una posición especificada. Con puntos de acoplamiento, hace que la experiencia de desplazarse por imágenes sea mucho más limpia y con mayor capacidad de respuesta.

Desplazamiento con un único punto de acoplamiento

InteractionTracker e InertiaModifiers

Al crear experiencias de manipulación personalizadas con InteractionTracker, puede crear experiencias de movimiento de punto de acoplamiento mediante inerciaModifiers. Los inerciaModifiers son básicamente una manera de definir dónde o cómo InteractionTracker llega a su destino al entrar en el estado De inercia. Puede aplicar InertiaModifiers para afectar a las propiedades X o Y o Scale de InteractionTracker.

Hay 3 tipos de InerciaModifiers:

  • InteractionTrackerInertiaRestingValue: una manera de modificar la posición de reposo final después de una interacción o velocidad mediante programación. Un movimiento predefinido tomará InteractionTracker a esa posición.
  • InteractionTrackerInertiaMotion: una manera de definir un objeto InteractionTracker de movimiento específico se realizará después de una interacción o velocidad mediante programación. La posición final se derivará de este movimiento.
  • InteractionTrackerInertiaNaturalMotion: una manera de definir la posición de reposo final después de una interacción o velocidad programática, pero con una animación basada en física (NaturalMotionAnimation).

Al entrar en Inercia, InteractionTracker evalúa cada uno de los InerciaModifiers asignados a ella y determina si alguno de ellos se aplica. Esto significa que puede crear y asignar varios InerciaModifiers a interactionTracker, pero, al definir cada uno, debe hacer lo siguiente:

  1. Definir la condición: una expresión que define la instrucción condicional cuando se debe realizar este inerciamodifier específico. Esto a menudo requiere examinar la Propiedad NaturalRestingPosition de InteractionTracker (destino dado la inercia predeterminada).
  2. Definir restingValue/Motion/NaturalMotion: defina la expresión de valor restante real, la expresión de movimiento o naturalMotionAnimation que tiene lugar cuando se cumple la condición.

Nota:

El aspecto de condición de los InerciaModifiers solo se evalúa una vez cuando InteractionTracker entra en inercia. Sin embargo, solo para InertiaMotion, la expresión de movimiento se evalúa cada fotograma del modificador cuya condición es verdadera.

Ejemplo

Ahora echemos un vistazo a cómo puede usar InertiaModifiers para crear algunas experiencias de punto de acoplamiento para volver a crear el lienzo de desplazamiento de las imágenes. En este ejemplo, cada manipulación está pensada para desplazarse potencialmente a través de una sola imagen: esto se conoce a menudo como puntos de acoplamiento obligatorios únicos.

Comencemos configurando InteractionTracker, VisualInteractionSource y la expresión que aprovecharán la posición de 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);
}

A continuación, dado que un solo comportamiento de punto de acoplamiento obligatorio moverá el contenido hacia arriba o hacia abajo, necesitará dos modificadores de inercia diferentes: uno que mueve el contenido desplazable hacia arriba y otro que lo mueve hacia abajo.

// Snap-Point to move the content up
var snapUpModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
// Snap-Point to move the content down
var snapDownModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);

Se determina si se debe ajustar o reducir en función de dónde InteractionTracker se colocaría naturalmente en relación con la distancia de acoplamiento: la distancia entre las ubicaciones de acoplamiento. Si ha pasado el punto medio, a continuación, acompáguelo; de lo contrario, acompáguelo. (En este ejemplo, se almacena la distancia de ajuste en un 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);

Este diagrama proporciona una descripción visual a la lógica que está ocurriendo:

Diagrama modificador de inercia

Ahora solo tiene que definir los valores de resting para cada InerciaModifier: mueva la posición de InteractionTracker a la posición de ajuste anterior o la siguiente.

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);

Por último, agregue Los inerciaModifiers a InteractionTracker. Ahora, cuando InteractionTracker entra en inerciaState, comprobará las condiciones de los InerciaModifiers para ver si se debe modificar su posición.

var modifiers = new InteractionTrackerInertiaRestingValue[] { 
snapUpModifier, snapDownModifier };
_tracker.ConfigurePositionYInertiaModifiers(modifiers);