Partilhar via


Criar pontos de ajuste com modificadores de inércia

Neste artigo, nos aprofundamos em como usar o recurso InertiaModifier do InteractionTracker para criar experiências de movimento que se ajustam a um ponto especificado.

Pré-requisitos

Aqui, assumimos que você está familiarizado com os conceitos discutidos nestes artigos:

O que são snap points e por que eles são úteis?

Ao criar experiências de manipulação personalizadas, às vezes é útil criar pontos de posição especializados dentro da tela rolável/ampliável na qual o InteractionTracker sempre descansará. Frequentemente, são chamados pontos de referência.

Observe no exemplo a seguir como a rolagem pode deixar a interface do usuário em uma posição estranha entre as diferentes imagens:

Rolagem sem pontos de ajuste

Se adicionar pontos de ajuste, quando parar de deslocar entre as imagens, elas posicionam-se numa posição especificada. Com pontos de ajuste, torna a experiência de percorrer imagens muito mais limpa e responsiva.

Rolagem com um único ponto de ajuste

InteractionTracker e Modificadores de Inércia

Ao criar experiências de manipulação personalizadas com o InteractionTracker, você pode criar experiências de movimento de ponto de ajuste utilizando InertiaModifiers. InertiaModifiers são essencialmente uma maneira de definir onde ou como o InteractionTracker chega ao seu destino ao entrar no estado de inércia. Você pode aplicar InertiaModifiers para afetar a posição X ou Y ou as propriedades Scale do InteractionTracker.

Existem 3 tipos de InertiaModifiers:

  • InteractionTrackerInertiaRestingValue – uma maneira de modificar a posição final de repouso após uma interação ou velocidade programática. Um movimento predefinido levará o InteractionTracker a essa posição.
  • InteractionTrackerInertiaMotion – uma maneira de definir um movimento específico que o InteractionTracker executará após uma interação ou velocidade programática. A posição final será derivada desta moção.
  • InteractionTrackerInertiaNaturalMotion – uma maneira de definir a posição final de repouso após uma interação ou velocidade programática, mas com uma animação baseada em física (NaturalMotionAnimation).

Ao entrar em Inertia, o InteractionTracker avalia cada um dos InertiaModifiers que lhe foram atribuídos e determina se algum deles se aplica. Isso significa que você pode criar e atribuir vários InertiaModifiers a um InteractionTracker, mas, ao definir cada um, você precisa fazer o seguinte:

  1. Defina a Condição – uma expressão que especifica a instrução condicional em que este InertiaModifier específico deve ser aplicado. Isso geralmente requer olhar para a posição de repouso natural do InteractionTracker (destino dado a inércia padrão).
  2. Defina o RestingValue/Motion/NaturalMotion – defina a expressão real do valor de repouso, expressão de movimento ou NaturalMotionAnimation que ocorre quando a condição é atendida.

Observação

O aspecto de condição dos InertiaModifiers é avaliado apenas uma vez quando o InteractionTracker entra em inércia. No entanto, apenas para InertiaMotion, a expressão de movimento é avaliada a cada quadro para o modificador cuja condição é verdadeira.

Exemplo

Agora vejamos como pode usar *InertiaModifiers* para criar algumas experiências de ponto de encaixe para recriar a galeria de imagens rolante. Neste exemplo, cada manipulação destina-se a mover-se potencialmente através de uma única imagem – isto é frequentemente referido como Pontos de Paragem Obrigatórios.

Vamos começar configurando o InteractionTracker, o VisualInteractionSource e o Expression que aproveitarão a posição do 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);
}

Em seguida, como um comportamento de Ponto de Ajuste Obrigatório Único moverá o conteúdo para cima ou para baixo, você precisará de dois modificadores de inércia diferentes: um que mova o conteúdo rolável para cima e outro que o mova para baixo.

// 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 o snap up ou down deve ser determinado com base em onde o InteractionTracker naturalmente pousará em relação à distância de snap – a distância entre os locais de snap. Se passar da metade, então desloque para baixo, caso contrário, desloque para cima. (Neste exemplo, você armazena a distância de ajuste em um 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 dá uma descrição visual da lógica que está acontecendo:

Diagrama modificador de inércia

Agora você só precisa definir os Valores de Repouso para cada InertiaModifier: mova a posição do InteractionTracker para a posição de ajuste anterior ou para a próxima.

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

Finalmente, adicione os InertiaModifiers ao InteractionTracker. Agora, quando o InteractionTracker entra no seu InertiaState, irá verificar as condições dos seus InertiaModifiers para ver se a sua posição deve ser modificada.

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