Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las animaciones lineales con fotogramas clave, las animaciones con fotogramas clave con un valor KeySpline o las funciones de aceleración son tres técnicas diferentes para un escenario prácticamente idéntico: crear una animación con guion gráfico que sea un poco más compleja y que utilice un comportamiento de animación no lineal desde un estado inicial hasta un estado final.
Prerrequisitos
Asegúrese de que ha leído el tema Animaciones con guion gráfico. Este tema se basa en los conceptos de animación que se explicaron en animaciones con guion gráfico y no volverá a pasar por ellos. Por ejemplo, Animaciones con guion gráfico describe cómo definir el objetivo de las animaciones, los guiones gráficos como recursos y los valores de propiedades de la línea de tiempo, tales como Duración, FillBehavior, etc.
Animación mediante animaciones de fotogramas clave
Las animaciones de fotogramas clave permiten más de un valor de destino al que se llega en un punto a lo largo de la línea de tiempo de la animación. En otras palabras, cada fotograma clave puede especificar un valor intermedio diferente y el último fotograma clave alcanzado es el valor de animación final. Al especificar varios valores para animar, puede crear animaciones más complejas. Las animaciones con fotogramas clave también permiten diferentes lógicas de interpolación, cada una de las cuales se implementa como una subclase KeyFrame distinta según el tipo de animación. En concreto, cada tipo de animación de fotograma clave tiene una variación Discrete, Linear, Spline y Easing de su clase KeyFrame para especificar sus fotogramas clave. Por ejemplo, para especificar una animación que tenga como objetivo un Double y utilice fotogramas clave, se pueden declarar fotogramas clave con DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame y EasingDoubleKeyFrame. Puede usar cualquiera de estos tipos dentro de una sola colección KeyFrames para cambiar la interpolación cada vez que se alcanza un nuevo fotograma clave.
En cuanto al comportamiento de la interpolación, cada fotograma clave controla la interpolación hasta que se alcanza su tiempo KeyTime. Su valor se alcanza también en ese momento. Si hay más fotogramas clave más allá, el valor se convierte en el valor inicial del siguiente fotograma clave de una secuencia.
Al principio de la animación, si no existe ningún fotograma clave con KeyTime de "0:0:0", el valor inicial es lo que sea el valor no animado de la propiedad. Esto es similar al comportamiento de una animación From/To/By si no hay From.
La duración de una animación de fotograma clave es igual, de manera implícita, al valor KeyTime más alto establecido en cualquiera de sus fotogramas clave. Puedes establecer una Duración explícita si lo deseas, pero ten cuidado de que no sea más corta que un KeyTime en tus propios fotogramas clave, ya que, de lo contrario, se cortará parte de la animación.
Además de Duración, puedes establecer todas las propiedades basadas en Timeline en una animación de fotogramas clave, igual que con una animación Desde/Hasta/Por, ya que las clases de animación de fotogramas clave también derivan de Timeline. Estos son:
- AutoReverse: una vez alcanzado el último fotograma clave, los fotogramas se repiten en orden inverso desde el final. Esto duplica la duración aparente de la animación.
- BeginTime: retrasa el inicio de la animación. La línea de tiempo para los valores KeyTime de los fotogramas no empieza a contar hasta que se alcanza BeginTime, por lo que no hay riesgo de que se corten fotogramas
- FillBehavior: controla lo que sucede cuando se alcanza el último fotograma clave. FillBehavior no tiene ningún efecto en ningún fotograma clave intermedio.
-
RepeatBehavior:
- Si se establece en Forever, los fotogramas clave y su escala de tiempo se repiten infinitamente.
- Si se establece en un recuento de iteraciones, la línea de tiempo se repite ese número de veces.
- Si se establece en Duration, la escala de tiempo se repite hasta que se alcanza ese tiempo. Esto podría truncar la animación a mitad de la secuencia de fotogramas clave, si no es un factor entero de la duración implícita de la línea de tiempo.
- SpeedRatio (no usado habitualmente)
Fotogramas clave lineales
Los fotogramas clave lineales dan como resultado una interpolación lineal simple del valor hasta que se alcanza el KeyTime del fotograma. Este comportamiento de interpolación es el más parecido a las animaciones más simples From/To/By descritas en el tema Animaciones con guion gráfico.
A continuación se explica cómo utilizar una animación de fotogramas clave para escalar la altura de renderizado de un rectángulo, utilizando fotogramas clave lineales. En este ejemplo se ejecuta una animación en la que el alto del rectángulo aumenta ligeramente y linealmente durante los primeros 4 segundos y, a continuación, se escala rápidamente durante el último segundo hasta que el rectángulo sea doble el alto inicial.
<StackPanel>
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
<LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:4"/>
<LinearDoubleKeyFrame Value="2" KeyTime="0:0:5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</StackPanel.Resources>
</StackPanel>
Fotogramas clave discretos
Los fotogramas clave discretos no usan ninguna interpolación en absoluto. Cuando se alcanza un KeyTime, simplemente se aplica el nuevo Value. Dependiendo de la propiedad de la interfaz de usuario que se esté animando, esto suele producir una animación que parece "dar un salto""." Asegúrate de que este es el comportamiento estético que realmente quieres. Puedes minimizar los saltos aparentes aumentando el número de fotogramas clave que declaras, pero si una animación suave es tu objetivo, podrías estar mejor usando fotogramas clave lineales o spline en su lugar.
Nota:
Los fotogramas clave discretos son la única manera de animar un valor que no es de tipo Double, Point o Color, con un DiscreteObjectKeyFrame. Lo analizaremos con más detalle más adelante en este tema.
Fotogramas clave de spline
Un marco clave spline crea una transición variable entre valores según el valor de la propiedad KeySpline . Esta propiedad especifica los puntos de control primero y segundo de una curva Bezier, que describe la aceleración de la animación. Básicamente, un KeySpline define una relación de función en función del tiempo en la que el gráfico de función-tiempo tiene la forma de esa curva de Bézier. Normalmente, se especifica un valor KeySpline en una cadena de atributo abreviado XAML que tiene cuatro valores Double separados por espacios o comas. Estos valores son pares "X,Y" para dos puntos de control de la curva Bezier. "X" es la hora y "Y" es el modificador de función para el valor. Cada valor siempre debe estar comprendido entre 0 y 1 ambos inclusive. Sin modificación del punto de control en una keySpline, la línea recta de 0,0 a 1,1 es la representación de una función a lo largo del tiempo para una interpolación lineal. Los puntos de control modifican la forma de esa curva y, por lo tanto, el comportamiento de la función a lo largo del tiempo para la animación de spline. Es probable que sea mejor ver esto visualmente como un gráfico.
El siguiente ejemplo muestra tres fotogramas clave diferentes aplicados a una animación, siendo el último una animación de spline clave para un valor Double (SplineDoubleKeyFrame). Observe la cadena "0.6,0.0 0.9,0.00" aplicada a KeySpline. Esto genera una curva en la que la animación parece ejecutarse lentamente al principio, pero luego alcanza rápidamente el valor justo antes de alcanzar KeyTime .
<Storyboard x:Name="myStoryboard">
<!-- Animate the TranslateTransform's X property
from 0 to 350, then 50,
then 200 over 10 seconds. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="MyAnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:10" EnableDependentAnimation="True">
<!-- Using a LinearDoubleKeyFrame, the rectangle moves
steadily from its starting position to 500 over
the first 3 seconds. -->
<LinearDoubleKeyFrame Value="500" KeyTime="0:0:3"/>
<!-- Using a DiscreteDoubleKeyFrame, the rectangle suddenly
appears at 400 after the fourth second of the animation. -->
<DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4"/>
<!-- Using a SplineDoubleKeyFrame, the rectangle moves
back to its starting point. The
animation starts out slowly at first and then speeds up.
This KeyFrame ends after the 6th second. -->
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:6"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Fotogramas clave con aceleración
Un fotograma clave con aceleración es aquel en el que se aplica una interpolación, y la función de dicha interpolación a lo largo del tiempo se controla mediante varias fórmulas matemáticas predefinidas. En realidad, se puede obtener un resultado muy similar con un fotograma clave de spline que con algunos de los tipos de funciones de aceleración, pero también hay algunas funciones de aceleración, como BackEase, que no se pueden reproducir con una spline.
Para aplicar una función de suavizado a un fotograma clave de suavizado, estableces la propiedad EasingFunction como un elemento de propiedad en XAML para ese fotograma clave. Como valor, especifica un elemento de objeto para uno de los tipos de función de aceleración.
En este ejemplo se aplica un CubicEase y, a continuación, un BounceEase como fotogramas clave sucesivos a DoubleAnimation para crear un efecto de rebote.
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames Duration="0:0:10"
Storyboard.TargetProperty="Height"
Storyboard.TargetName="myEllipse">
<!-- This keyframe animates the ellipse up to the crest
where it slows down and stops. -->
<EasingDoubleKeyFrame Value="-300" KeyTime="00:00:02">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<!-- This keyframe animates the ellipse back down and makes
it bounce. -->
<EasingDoubleKeyFrame Value="0" KeyTime="00:00:06">
<EasingDoubleKeyFrame.EasingFunction>
<BounceEase Bounces="5"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Este es solo un ejemplo de función de suavizado. Trataremos más en la sección siguiente.
Funciones de suavizado
Las funciones de suavizado permiten aplicar fórmulas matemáticas personalizadas a las animaciones. Las operaciones matemáticas suelen ser útiles para producir animaciones que simulan la física del mundo real en un sistema de coordenadas 2D. Por ejemplo, puede que desee que un objeto rebote o se comporte de forma realista como si estuviera en un muelle. Podrías utilizar fotogramas clave o incluso animaciones Desde/Hasta/Por para aproximarte a estos efectos, pero supondría una cantidad considerable de trabajo y la animación sería menos precisa que si se utilizara una fórmula matemática.
Las funciones de aceleración se pueden aplicar a animaciones de tres maneras:
- Utilizando un fotograma clave de aceleración en una animación de fotogramas clave, tal y como se describe en la sección anterior. Utilice EasingColorKeyFrame.EasingFunction, EasingDoubleKeyFrame.EasingFunction o EasingPointKeyFrame.EasingFunction.
- Estableciendo la propiedad EasingFunction en uno de los tipos de animación From/To/By. Use ColorAnimation.EasingFunction, DoubleAnimation.EasingFunction o PointAnimation.EasingFunction.
- Al establecer GeneratedEasingFunction como parte de visualTransition. Esto es específico para definir estados visuales para los controles; para obtener más información, consulta GeneratedEasingFunction o Storyboards para estados visuales.
Esta es una lista de las funciones de suavizado:
- BackEase: retira el movimiento de una animación ligeramente antes de empezar a animarse en la ruta indicada.
- BounceEase: crea un efecto de rebote.
- CircleEase: crea una animación que acelera o ralentiza mediante una función circular.
- CubicEase: crea una animación que acelera o ralentiza mediante la fórmula f(t) = t3.
- ElasticEase: crea una animación similar a un resorte que oscila hacia atrás y hacia delante hasta que llega a descansar.
- ExponentialEase: crea una animación que acelera o ralentiza mediante una fórmula exponencial.
- PowerEase: crea una animación que acelera o ralentiza mediante la fórmula f(t) = tp donde p es igual a la propiedad Power .
- QuadraticEase: crea una animación que acelera o decelera mediante la fórmula f(t) = t2.
- QuarticEase: crea una animación que acelera o ralentiza mediante la fórmula f(t) = t4.
- QuinticEase: cree una animación que acelere o decelere mediante la fórmula f(t) = t5.
- SineEase: crea una animación que acelera o ralentiza mediante una fórmula sine.
Algunas de las funciones de aceleración tienen sus propias propiedades. Por ejemplo, BounceEase tiene dos propiedades Bounces y Bounciness que modifican el comportamiento de función a lo largo del tiempo de ese BounceEase determinado. Otras funciones de aceleración, como CubicEase , no tienen propiedades distintas de la propiedad EasingMode que comparten todas las funciones de aceleración y siempre producen el mismo comportamiento de función a lo largo del tiempo.
Algunas de estas funciones de aceleración presentan cierta superposición, dependiendo de cómo configures las propiedades en aquellas funciones de aceleración que disponen de propiedades. Por ejemplo, QuadraticEase es exactamente igual que PowerEase con Power igual a 2. Y CircleEase es básicamente un valor predeterminado ExponentialEase.
La función de aceleración BackEase es única porque puede modificar el valor fuera del rango normal establecido por From/To o por los valores de los fotogramas clave. Inicia la animación cambiando el valor en la dirección opuesta como se esperaría de un comportamiento From/To normal, vuelve al valor From o inicial de nuevo y a continuación, ejecuta la animación como es normal.
En un ejemplo anterior, mostramos cómo declarar una función de aceleración para una animación con fotogramas clave. En el siguiente ejemplo se aplica una función de suavizado a una animación From/To/By.
<StackPanel x:Name="LayoutRoot" Background="White">
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimation From="30" To="200" Duration="00:00:3"
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="2" EasingMode="EaseOut"
Bounciness="2"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</StackPanel.Resources>
<Rectangle x:Name="myRectangle" Fill="Blue" Width="200" Height="30"/>
</StackPanel>
Cuando se aplica una función de aceleración a una animación From/To/By, se modifican las características temporales de la función, es decir, cómo se interpola el valor entre los valores From y To a lo largo de la Duration de la animación. Sin una función de aceleración, sería una interpolación lineal.
Animaciones de objeto de valor discretas
Un tipo de animación merece una mención especial porque es la única manera de aplicar un valor animado a las propiedades que no son de tipo Double, Point o Color. Esta es la animación con fotogramas clave ObjectAnimationUsingKeyFrames. La animación mediante valores object es diferente porque no hay posibilidad de interpolar los valores entre los fotogramas. Cuando se alcanza el KeyTime del fotograma, el valor animado se establece inmediatamente en el Value especificado en el fotograma clave. Dado que no hay interpolación, solo hay un fotograma clave que se usa en la colección de fotogramas clave ObjectAnimationUsingKeyFrames : DiscreteObjectKeyFrame.
El valor de discreteObjectKeyFrame se establece a menudo mediante la sintaxis del elemento de propiedad, ya que el valor del objeto que intenta establecer a menudo no se puede expresar como una cadena para rellenar la sintaxis de atributo Value . Todavía puede usar la sintaxis de atributo si usa una referencia como StaticResource.
Un lugar donde verá un objectAnimationUsingKeyFrames usado en las plantillas predeterminadas es cuando una propiedad de plantilla hace referencia a un recurso Brush . Estos recursos son objetos SolidColorBrush , no solo un valor color y usan recursos definidos como temas del sistema (ThemeDictionaries). Se pueden asignar directamente a un valor de tipo Brush, como TextBlock.Foreground y no es necesario usar el destino indirecto. Pero dado que solidColorBrush no es Double, Point o Color, debe usar objectAnimationUsingKeyFrames para usar el recurso.
<Style x:Key="TextButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<TextBlock x:Name="Text"
Text="{TemplateBinding Content}"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
...
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
También puede usar ObjectAnimationUsingKeyFrames para animar propiedades que usan un valor de enumeración. Este es otro ejemplo de un estilo con nombre que procede de las plantillas predeterminadas de Windows Runtime. Observe cómo establece la propiedad Visibility que toma una constante de enumeración Visibility . En este caso, puede establecer el valor mediante la sintaxis de atributo. Solo necesita el nombre de constante no calificado de una enumeración para configurar una propiedad con un valor de enumeración, por ejemplo, "Collapsed".
<Style x:Key="BackButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
... <VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="Collapsed" KeyTime="0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
...
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Puedes utilizar más de un DiscreteObjectKeyFrame para un conjunto de fotogramas ObjectAnimationUsingKeyFrames. Esta podría ser una manera interesante de crear una animación de "presentación con diapositivas" animando el valor de Image.Source, como escenario de ejemplo para donde varios valores de objeto podrían ser útiles.