Animações baseadas em ponteiro

Este artigo mostra como usar a posição de um ponteiro em aplicativos WinUI e SDK de Aplicativos do Windows para criar experiências dinâmicas de "manter o cursor".

Pré-requisitos

Aqui, presumimos que você esteja familiarizado com os conceitos discutidos nestes artigos:

Por que criar experiências guiadas pela posição do ponteiro?

Na linguagem de design fluente, o toque não é a única maneira de interagir com a interface do usuário. Os usuários finais interagem com aplicativos usando outras modalidades de entrada, como mouse e caneta, uma vez que os aplicativos WinUI podem abranger vários formatos de dispositivos. O uso de dados de posição dessas outras modalidades de entrada oferece uma oportunidade para que os usuários finais se sintam ainda mais conectados com seu aplicativo.

As experiências orientadas à posição do ponteiro permitem aproveitar a posição na tela de uma modalidade de entrada de ponteiro para criar experiências adicionais de movimento e interface do usuário para seu aplicativo. Essas experiências geralmente podem fornecer contexto adicional e comentários aos usuários finais sobre o comportamento e a estrutura da interface do usuário. A experiência não é mais um fluxo unidirecional, mas começa a se tornar um fluxo bidirecional onde o usuário final interage através do seu método de interação e a interface do usuário do aplicativo pode responder de volta.

Alguns exemplos incluem:

  • Animando a posição de um Foco para seguir o cursor

    Exemplo de destaque de ponteiro

  • Girar uma imagem com base na posição de um ponteiro

    Exemplo de rotação de ponteiro

Usando PointerPositionPropertySet

Você pode criar essas experiências usando o PointerPositionPropertySet. Este PropertySet é criado para um UIElement manter a posição do ponteiro enquanto o UIElement é testado positivamente. O valor da posição é relativo ao espaço de coordenadas do UIElement (uma posição de <0,0> é o canto superior esquerdo do UIElement). Em seguida, você pode aproveitar esse conjunto de propriedades definidas em uma animação para controlar o movimento de outra propriedade.

Para cada uma das diferentes Modalidades de Entrada do Ponteiro, há vários estados de entrada em que a posição é alterada: Suspenso, Pressionado, Pressionado e Movido. O PointerPositionPropertySet mantém apenas a posição do ponteiro nos estados Hover, Pressionado, e Pressionado e Movido para Mouse e Caneta.

Etapas gerais para começar:

  1. Identifique o UIElement, você deseja ter a posição do ponteiro rastreada.
  2. Acesse o PointerPositionPropertySet via ElementCompositionPreview.
  3. Crie um ExpressionAnimation que faça referência à propriedade Position no PropertySet.
    • Não se esqueça de definir seu parâmetro de referência!
  4. Direcione a propriedade de um CompositionObject com o ExpressionAnimation.

Observação

É recomendável que você atribua o PropertySet retornado do método GetPointerPositionPropertySet a uma variável de classe. Isso garante que o conjunto de propriedades não seja limpo pela Coleta de Lixo e, portanto, não tenha nenhum efeito sobre a ExpressionAnimation na qual ele é referenciado. ExpressionAnimations não mantém uma referência forte a nenhum dos objetos usados na equação.

Exemplo

Vamos dar uma olhada em um exemplo em que utilizamos a posição hover de uma modalidade de entrada de mouse e de caneta para girar dinamicamente uma imagem.

Exemplo de rotação de ponteiro

A imagem é um UIElement, portanto, primeiro vamos obter uma referência ao PointerPositionPropertySet

_pointerPositionPropSet = ElementCompositionPreview.GetPointerPositionPropertySet(element);

Neste exemplo, você tem duas Expressões em jogo:

  • Uma expressão em que a imagem gira com base na distância em que o ponteiro está do centro da imagem. Quanto mais longe, mais rotação.
  • Uma expressão em que o eixo de rotação é alterado com base na posição do ponteiro. Você deseja que o eixo de rotação seja perpendicular ao vetor da posição.

Aqui, você define as duas Expressões, uma que tem como destino a propriedade RotationAngle e a outra a propriedade RotationAxis. Você faz referência ao PointerPositionPropertySet como qualquer outro PropertySet.

Neste exemplo, você está criando expressões usando as classes ExpressionBuilder .

// using EF = ExpressionBuilder.ExpressionFunctions;
// || DEFINE THE EXPRESSION FOR THE ROTATION ANGLE ||
var hoverPosition = _pointerPositionPropSet.GetSpecializedReference
<PointerPositionPropertySetReferenceNode>().Position;
var angleExpressionNode =
EF.Conditional(
 hoverPosition == new Vector3(0, 0, 0),
 ExpressionValues.CurrentValue.CreateScalarCurrentValue(),
 35 * ((EF.Clamp(EF.Distance(center, hoverPosition), 0, distanceToCenter) % distanceToCenter) / distanceToCenter));
_tiltVisual.StartAnimation("RotationAngleInDegrees", angleExpressionNode);

// || DEFINE THE EXPRESSION FOR THE ROTATION AXIS ||
var axisAngleExpressionNode = EF.Vector3(
-(hoverPosition.Y - center.Y) * EF.Conditional(hoverPosition.Y == center.Y, 0, 1),
 (hoverPosition.X - center.X) * EF.Conditional(hoverPosition.X == center.X, 0, 1),
 0);
_tiltVisual.StartAnimation("RotationAxis", axisAngleExpressionNode);

Consulte também