Animaciones basadas en relaciones

En este artículo se proporciona información general sobre cómo crear animaciones basadas en relaciones mediante ExpressionAnimations de composición.

Experiencias basadas en relaciones dinámicas

Al crear experiencias de movimiento en una aplicación, hay ocasiones en las que el movimiento no se basa en el tiempo, sino que depende de una propiedad en otro objeto. KeyFrameAnimations no pueden expresar estos tipos de experiencias de movimiento muy fácilmente. En estas instancias específicas, el movimiento ya no debe ser discreto y predefinido. En su lugar, el movimiento puede adaptarse dinámicamente en función de su relación con otras propiedades de objeto. Por ejemplo, puede animar la opacidad de un objeto en función de su posición horizontal. Otros ejemplos incluyen experiencias de movimiento como encabezados pegajosos y parallax.

Estos tipos de experiencias de movimiento permiten crear una interfaz de usuario que se sienta más conectada, en lugar de sentirse singular e independiente. Para el usuario, esto da la impresión de una experiencia de interfaz de usuario dinámica.

Círculo en órbita

Vista de lista con parallax

Uso de ExpressionAnimations

Para crear experiencias de movimiento basadas en relaciones, use el tipo ExpressionAnimation. ExpressionAnimations (o Expresiones para abreviar), son un nuevo tipo de animación que permite expresar una relación matemática, una relación que el sistema usa para calcular el valor de una propiedad de animación cada fotograma. Por otra parte, las expresiones son simplemente una ecuación matemática que define el valor deseado de una propiedad de animación por fotograma. Las expresiones son un componente muy versátil que se puede usar en una amplia variedad de escenarios, entre los que se incluyen:

Al trabajar con ExpressionAnimations, hay un par de cosas que merece la pena mencionar por adelantado:

  • Never Ending: a diferencia de su elemento del mismo nivel KeyFrameAnimation, las expresiones no tienen una duración finita. Dado que las expresiones son relaciones matemáticas, son animaciones que constantemente se "ejecutan". Si lo desea, tiene la opción de detener estas animaciones.
  • En ejecución, pero no siempre evaluando: el rendimiento siempre es un problema con las animaciones que se ejecutan constantemente. Sin embargo, no es necesario preocuparse, el sistema es lo suficientemente inteligente como para que la expresión solo vuelva a evaluar si alguna de sus entradas o parámetros ha cambiado.
  • Resolución en el tipo de objeto correcto: dado que las expresiones son relaciones matemáticas, es importante asegurarse de que la ecuación que define la expresión se resuelve en el mismo tipo de la propiedad dirigida por la animación. Por ejemplo, si anima Offset, la expresión debe resolverse en un tipo Vector3.

Componentes de una expresión

Al crear la relación matemática de una expresión, hay varios componentes principales:

  • Parámetros: valores que representan valores constantes o referencias a otros objetos Composition.
  • Operadores matemáticos: los operadores matemáticos típicos más(+), menos(-), multiplicar(*), divide(/) que unen parámetros para formar una ecuación. También se incluyen operadores condicionales como mayor que(>), equal(==), operador ternario (condición ? ifTrue : ifFalse), etc.
  • Funciones matemáticas: funciones matemáticas o accesos directos basados en System.Numerics. Para obtener una lista completa de las funciones admitidas, vea ExpressionAnimation.

Las expresiones también admiten un conjunto de palabras clave: frases especiales que tienen un significado distinto solo dentro del sistema ExpressionAnimation. Estos se enumeran (junto con la lista completa de funciones matemáticas) en la documentación de ExpressionAnimation .

Creación de expresiones con ExpressionBuilder

Hay dos opciones para compilar expresiones en la aplicación para UWP:

  1. Compile la ecuación como una cadena a través de la API pública oficial.
  2. Compile la ecuación en un modelo de objetos con seguridad de tipos a través de la herramienta ExpressionBuilder incluida con el Kit de herramientas de la comunidad de Windows.

Para este documento, definiremos nuestras expresiones mediante ExpressionBuilder.

Parámetros

Los parámetros constituyen el núcleo de una expresión. Hay dos tipos de parámetros:

  • Constantes: son parámetros que representan variables System.Numeric con tipo. Estos parámetros obtienen sus valores asignados una vez cuando se inicia la animación.
  • Referencias: estos son parámetros que representan referencias a CompositionObjects: estos parámetros obtienen continuamente sus valores actualizados después de iniciar una animación.

En general, Las referencias son el aspecto principal de cómo la salida de una expresión puede cambiar dinámicamente. A medida que cambian estas referencias, la salida de la expresión cambia como resultado. Si crea la expresión con cadenas o las usa en un escenario de plantillas (mediante la expresión para tener como destino varios CompositionObjects), deberá asignar un nombre y establecer los valores de los parámetros. Consulta la sección Ejemplos para obtener más información.

Trabajar con KeyFrameAnimations

Las expresiones también se pueden usar con KeyFrameAnimations. En estos casos, quiere usar una expresión para definir el valor de un fotograma clave en un momento dado: estos tipos de fotogramas clave se denominan ExpressionKeyFrames.

KeyFrameAnimation.InsertExpressionKeyFrame(Single, String)
KeyFrameAnimation.InsertExpressionKeyFrame(Single, ExpressionNode)

Sin embargo, a diferencia de ExpressionAnimations, ExpressionKeyFrames solo se evalúa una vez cuando se inicia KeyFrameAnimation. Tenga en cuenta que no se pasa expressionAnimation como valor del fotograma clave, sino una cadena (o expressionNode, si usa ExpressionBuilder).

Ejemplo

Ahora vamos a ver un ejemplo de uso de expresiones, específicamente el ejemplo PropertySet de la Galería de ejemplos de interfaz de usuario de Windows. Veremos la expresión que administra el comportamiento del movimiento de órbita de la bola azul.

Círculo en órbita

Hay tres componentes en juego para la experiencia total:

  1. KeyFrameAnimation, animando el desplazamiento Y de la bola roja.
  2. PropertySet con una propiedad Rotation que ayuda a unidades de la órbita, animadas por otra KeyFrameAnimation.
  3. ExpresiónAnimation que impulsa el Desplazamiento de la bola azul que hace referencia al desplazamiento de bola roja y la propiedad Rotation para mantener una órbita perfecta.

Nos centraremos en la expresiónAnimation definida en #3. También usaremos las clases ExpressionBuilder para construir esta expresión. Al final se muestra una copia del código que se usa para compilar esta experiencia a través de cadenas.

En esta ecuación, hay dos propiedades a las que debe hacer referencia desde propertySet; uno es un desplazamiento de punto central y el otro es la rotación.

var propSetCenterPoint =
_propertySet.GetReference().GetVector3Property("CenterPointOffset");

// This rotation value will animate via KFA from 0 -> 360 degrees
var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");

A continuación, debe definir el componente Vector3 que tenga en cuenta la rotación en órbita real.

var orbitRotation = EF.Vector3(
    EF.Cos(EF.ToRadians(propSetRotation)) * 150,
    EF.Sin(EF.ToRadians(propSetRotation)) * 75, 0);

Nota

EF es una notación abreviada "using" para definir ExpressionFunctions.

using EF = Microsoft.Toolkit.Uwp.UI.Animations.Expressions.ExpressionFunctions;

Por último, combine estos componentes juntos y haga referencia a la posición de la Bola Roja para definir la relación matemática.

var orbitExpression = redSprite.GetReference().Offset + propSetCenterPoint + orbitRotation;
blueSprite.StartAnimation("Offset", orbitExpression);

En una situación hipotética, qué ocurre si desea usar esta misma expresión pero con otros dos objetos visuales, lo que significa 2 conjuntos de círculos en órbita. Con CompositionAnimations, puede volver a usar la animación y tener como destino varios CompositionObjects. Lo único que debe cambiar al usar esta expresión para el caso de órbita adicional es la referencia al objeto visual. Llamamos a esta plantillas.

En este caso, modificará la expresión que creó anteriormente. En lugar de "obtener" una referencia a CompositionObject, se crea una referencia con un nombre y, a continuación, se asignan valores diferentes:

var orbitExpression = ExpressionValues.Reference.CreateVisualReference("orbitRoundVisual");
orbitExpression.SetReferenceParameter("orbitRoundVisual", redSprite);
blueSprite.StartAnimation("Offset", orbitExpression);
// Later on … use same Expression to assign to another orbiting Visual
orbitExpression.SetReferenceParameter("orbitRoundVisual", yellowSprite);
greenSprite.StartAnimation("Offset", orbitExpression);

Este es el código si definió la expresión con cadenas a través de la API pública.

ExpressionAnimation expressionAnimation = compositor.CreateExpressionAnimation("visual.Offset + " +
    "propertySet.CenterPointOffset + " +
    "Vector3(cos(ToRadians(propertySet.Rotation)) * 150," + "sin(ToRadians(propertySet.Rotation)) * 75, 0)");
    
var propSetCenterPoint = _propertySet.GetReference().GetVector3Property("CenterPointOffset");
var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");
expressionAnimation.SetReferenceParameter("propertySet", _propertySet);
expressionAnimation.SetReferenceParameter("visual", redSprite);