Animações baseadas em ponteiro

Este artigo mostra como usar a posição de um ponteiro nas aplicações WinUI e SDK de Aplicações Windows para criar experiências dinâmicas de "manter-se no cursor".

Pré-requisitos

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

Porquê criar experiências orientadas por posição do ponteiro?

Na linguagem de design Fluent, o toque não é a única forma de interagir com a interface. Como as aplicações WinUI podem abranger vários formatos de dispositivos, os utilizadores finais interagem com aplicações com outras modalidades de entrada, como Rato e Caneta. Utilizar dados de posição destas outras modalidades de entrada oferece uma oportunidade para que os utilizadores finais se sintam ainda mais ligados à sua aplicação.

As experiências orientadas pela posição do ponteiro permitem-lhe aproveitar a posição no ecrã de uma modalidade de entrada do ponteiro para criar experiências adicionais de movimento e interface para a sua aplicação. Estas experiências podem frequentemente fornecer contexto adicional e feedback aos utilizadores finais sobre o comportamento e a estrutura da interface. A experiência deixa de ser um fluxo unidirecional, mas começa a tornar-se num fluxo bidirecional, onde o utilizador final fornece informações com a sua modalidade de entrada e a interface da aplicação pode responder.

Eis alguns exemplos:

  • Animar a posição de um Spotlight de modo a seguir o cursor

    Exemplo de destaque de ponteiro

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

    Exemplo de rotação do ponteiro

Usando PointerPositionPropertySet

Pode criar estas experiências usando o PointerPositionPropertySet. Este PropertySet é criado para que um UIElement mantenha a posição do ponteiro enquanto o UIElement é testado positivamente por hits. 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). Pode então usar esta propriedade configurada numa animação para controlar o movimento de outra propriedade.

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

Passos gerais para começar:

  1. Identifique o UIElement, deseja que a posição do ponteiro seja rastreada.
  2. Acede ao PointerPositionPropertySet através do ElementCompositionPreview.
  3. Crie uma ExpressionAnimation que faça referência à propriedade Position no PropertySet.
    • Não te esqueças de definir o teu parâmetro de referência!
  4. Apontar uma propriedade de um CompositionObject com a ExpressionAnimation.

Observação

Recomenda-se que atribua o PropertySet devolvido do método GetPointerPositionPropertySet a uma variável de classe. Isto garante que o conjunto de propriedades não seja eliminado por Garbage Collection, não tendo assim qualquer efeito na ExpressionAnimation em que é referenciado. As ExpressionAnimations não mantêm uma referência forte a nenhum dos objetos usados na equação.

Exemplo

Vamos analisar um exemplo onde utilizamos a posição de flutuar de uma modalidade de entrada de rato e caneta para rodar uma imagem de forma dinâmica.

Exemplo de rotação do ponteiro

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

_pointerPositionPropSet = ElementCompositionPreview.GetPointerPositionPropertySet(element);

Neste exemplo, tens duas Expressões em jogo:

  • Uma expressão em que a imagem gira com base na distância do ponteiro em relação ao centro da imagem. Quanto mais longe, mais rotação.
  • Uma expressão onde o eixo de rotação muda consoante a posição do apontador. Queres que o eixo de rotação seja perpendicular ao vetor da posição.

Aqui, defines as duas Expressões, uma que visa a propriedade RotationAngle e a outra a propriedade RotationAxis. Refere-se ao PointerPositionPropertySet como qualquer outro PropertySet.

Neste exemplo, está a construir 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