Animaciones de fotograma clave y animaciones de función de aceleración (XAML)

Guía básica: Relación de este tema con los demás. Consulta:

Las animaciones de fotograma clave lineales, las animaciones de fotograma clave con un valor KeySpline o las funciones de aceleración son tres técnicas distintas para prácticamente el mismo escenario: crear una animación de guión gráfico que es un poco más compleja y que tiene un comportamiento de animación no lineal desde un estado inicial hasta un estado final.

Requisitos previos

Asegúrate de que has leído el tema sobre las animaciones de guión gráfico. Este tema se basa en los conceptos de animación que se explicaron en el tema sobre animaciones de guión gráfico y no los explicaremos nuevamente. Por ejemplo, en la sección de animaciones de guión gráfico se describe cómo seleccionar como destino animaciones y guiones gráficos para usarlos como recursos, los valores de la propiedad Timeline tales como Duration, FillBehavior, etc.

Animación mediante animaciones de fotograma clave

Las animaciones de fotograma clave permiten que se alcance más de un valor de destino en un punto junto con la escala de tiempo de la animación. En otras palabras, cada fotograma clave puede especificar un valor intermedio diferente y el último fotograma clave que se alcanza se convierte en el valor de animación final. Si especificas varios valores para animar, puedes crear animaciones más complejas. Las animaciones de fotograma clave también permiten una lógica de interpolación distinta, las cuales se implementan como una subclase KeyFrame diferente según el tipo de animación. Específicamente, cada tipo de animación de fotograma clave presenta una variación de Discrete, Linear, Spline y Easing de su clase KeyFrame para especificar sus fotogramas clave. Por ejemplo, para especificar una animación que selecciona como destino Double y usa fotogramas clave, puedes declarar fotogramas clave con DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame y EasingDoubleKeyFrame. Puedes usar algunos de estos tipos, o todos, dentro de una única colección de KeyFrames, para cambiar la interpolación cada vez que se alcanza un nuevo fotograma clave.

En el caso del comportamiento de interpolación, cada fotograma clave controla la interpolación hasta que se alcanza el tiempo KeyTime. En ese momento también se alcanza su Value. Si hay más fotogramas clave detrás, el valor se convierte entonces en el valor inicial para el siguiente fotograma clave de una secuencia.

Al inicio de la animación, si no existe ningún fotograma clave con un KeyTime de "0:0:0", el valor inicial es igual al valor no animado de la propiedad. Esto es similar a cómo actúa una animación From/To/By si no hay un valor From.

La duración de una animación de fotograma clave es implícitamente la duración que equivale al valor más alto de KeyTime configurado en cualquiera de los fotogramas clave. Si quieres, puedes configurar un valor de Duration explícito, pero recuerda que no puede ser menor que el KeyTime de tus propios fotogramas clave; de lo contrario, cortarás parte de la animación.

Además de Duration, puedes configurar todas las propiedades basadas en Timeline en una animación de fotograma clave, tal como puedes hacerlo con una animación From/To/By, ya que las clases de animación de fotograma clave también derivan de Timeline. Estas son:

  • AutoReverse: una vez que se alcanza 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 escala de tiempo para los valores KeyTime de los fotogramas no inicia el recuento hasta que se alcanza el BeginTime, de modo que no hay riesgo de cortar los fotogramas.
  • FillBehavior: controla lo que sucede cuando se llega al último fotograma clave. FillBehavior no tiene ningún efecto en los fotogramas clave intermedios.
  • RepeatBehavior:
    • Si está establecido como Forever, los fotogramas clave y sus escalas de tiempo se repiten de manera indefinida.
    • Si está establecido como un recuento de iteraciones, la escala de tiempo se repite esa cantidad de veces.
    • Si está establecido como una Duration, la escala de tiempo se repite hasta llegar a dicho horario. Esto puede truncar parte de la animación en la secuencia de fotograma clave, si no es un factor entero de la duración implícita de la escala de tiempo.
  • SpeedRatio (no se utiliza frecuentemente)

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. El comportamiento de interpolación es lo que más se asemeja a las animaciones From/To/By más simples descritas en el tema Animaciones de guión gráfico.

Aquí te mostramos cómo usar una animación de fotograma clave para escalar el alto de un rectángulo con fotogramas clave lineales. Este ejemplo ejecuta una animación en la que el alto del rectángulo aumenta levemente, de manera lineal, durante los primeros cuatro segundos y, luego, escala rápidamente hasta el último segundo hasta que el rectángulo presenta el doble del 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. Cuando se llega a un KeyTime, simplemente se aplica el nuevo Value. Según la propiedad de interfaz de usuario que se está animando, por lo general, esto genera una animación que simula un "salto". Asegúrate de que este sea el comportamiento estético que realmente quieres. Puedes minimizar los saltos aparentes al aumentar la cantidad de fotogramas clave declarados, pero si tu objetivo es una animación suave, lo mejor es que uses en cambio fotogramas clave lineales o spline.

Nota  Los fotogramas clave discretos son la única forma de animar un valor que no es del tipo Double, Point y Color, con un DiscreteObjectKeyFrame. Analizaremos esto en mayor detalle más adelante en este tema.

Fotogramas clave spline

Un fotograma clave spline crea una transición variable entre valores de acuerdo con el valor de la propiedad KeySpline. Esta propiedad especifica el primer y el segundo punto de control de una curva Bézier, que describen la aceleración de la animación. Básicamente, un KeySpline define una función sobre una relación de tiempo en la que el gráfico de tiempo de la función tiene la forma de la curva Bézier. Por lo general, especificas un valor de KeySpline en una cadena de atributos XAML abreviada que tiene cuatro valores Double separados por espacios o comas. Estos valores son pares "X,Y" para dos puntos de control de la curva Bézier. "X" representa al tiempo e "Y" es el modificación de función para el valor. Cada valor debe estar comprendido siempre entre 0 y 1, inclusive. Sin una modificación del punto de control a un 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 cambian la forma de la curva y, por ende, el comportamiento de la función a lo largo del tiempo para la animación spline. Lo mejor es verlo en un gráfico. Puedes ejecutar la muestra del visualizador de spline clave de Silverlight en un explorador para ver de qué manera los puntos de control modifican la curva y cómo se ejecuta una animación de muestra cuando se la usa como un valor de KeySpline.

El ejemplo que sigue muestra tres fotogramas clave diferentes aplicados a una animación. El último es una animación spline clave para un valor Double (SplineDoubleKeyFrame). Observa la cadena "0.6,0.0 0.9,0.00" que se aplica para KeySpline. Se produce una curva en la que la animación parece ejecutarse lentamente al principio, pero luego alcanza con velocidad el valor justo antes de que se llegue al 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 de aceleración

Un fotograma clave de aceleración es un fotograma clave en el que se aplica interpolación, y la función a lo largo del tiempo de la interpolación está controlada por varias fórmulas matemáticas predefinidas. En realidad, puedes producir el mismo resultado con un fotograma clave spline que el que puedes obtener con algunos de los tipos de funciones de aceleración, pero hay algunas funciones de aceleración, tales como BackEase, que no puedes reproducir con un spline.

Para aplicar una función de aceleración a un fotograma clave de aceleración, debes establecer la propiedad EasingFunction como un elemento de propiedad en XAML para dicho fotograma clave. Para el valor, especifica un elemento de objeto para uno de los tipos de funciones de aceleración.

En este ejemplo se aplica CubicEase y, luego, 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 una función de aceleración. Podrás encontrar más información en la siguiente sección.

Funciones de aceleración

Las funciones de aceleración te permiten aplicar fórmulas matemáticas personalizadas a tus animaciones. Por lo general, las operaciones matemáticas resultan útiles para producir animaciones que simulan una física del mundo real en un sistema de coordenadas en 2D. Por ejemplo, es posible que quieras que un objeto rebote de forma realista o se comporte como si estuviera en una fuente. Podrías usar animaciones de fotogramas clave o From/To/By para mostrar estos efectos, pero representaría una carga de trabajo considerable y la animación resultaría menos realista que si usas una fórmula matemática.

Las funciones de aceleración se pueden aplicar a las animaciones de tres formas:

A continuación te indicamos una lista de funciones de aceleración:

  • BackEase: retira el movimiento de una animación un poquito antes de que comience la animación en la ruta indicada.
  • BounceEase: crea un efecto de rebote.
  • CircleEase: crea una animación que acelera o desacelera con una función circular.
  • CubicEase: crea una animación que acelera o desacelera con la fórmula f(t) = t3.
  • ElasticEase: crea una animación que se asemeja a la oscilación de una fuente hasta que se detiene.
  • ExponentialEase: crea una animación que acelera o desacelera con una fórmula exponencial.
  • PowerEase: crea una animación que acelera o desacelera con la fórmula f(t) = tp donde p equivale a la propiedad Power.
  • QuadraticEase: crea una animación que acelera o desacelera con la fórmula f(t) = t2.
  • QuarticEase: crea una animación que acelera o desacelera con la fórmula f(t) = t4.
  • QuinticEase: crea una animación que acelera o desacelera con la fórmula f(t) = t5.
  • SineEase: crea una animación que acelera o desacelera con una fórmula senoidal.

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 la función a lo largo del tiempo de dicho BounceEase en particular. Otras funciones de aceleración, como CubicEase, no tienen otras propiedades que no sean la propiedad EasingMode que comparten todas las funciones de aceleración y siempre producen el mismo comportamiento de la función a lo largo del tiempo.

Algunas de estas funciones de aceleración se superponen un poco, según cómo configures las propiedades en las funciones de aceleración que contienen propiedades. Por ejemplo, QuadraticEase es exactamente igual que PowerEase con Power que equivale a 2. Y CircleEase es básicamente un valor predeterminado de ExponentialEase.

La función de aceleración BackEase es única porque puede cambiar el valor fuera del intervalo normal establecido por From/To o los valores de fotogramas clave. Inicia la animación al cambiar el valor en la dirección contraria que se esperaría de un comportamiento From/To normal, vuelve al valor inicial o From y, luego, ejecuta la animación normalmente.

Puedes experimentar con diferentes funciones de aceleración mediante una muestra de Silverlight.

En un ejemplo anterior, mostramos cómo declarar una función de aceleración para una animación de fotograma clave. En el ejemplo siguiente se aplica una función de aceleración 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 cambian las características de la función a lo largo del tiempo con respecto a cómo el valor se interpola entre los valores From y To durante el transcurso de la Duration de la animación. Sin una función de aceleración, se trataría de una interpolación lineal.

Animaciones de valores de objetos discretas

Hay un tipo de animación que merece especial atención porque es la única forma en la que se puede aplicar un valor animado a las propiedades que no son del tipo Double, Point o Color. Se trata de la animación de fotograma clave ObjectAnimationUsingKeyFrames. La animación con valores Object es diferente porque no es posible interpolar los valores entre los fotogramas. Cuando se alcanza el KeyTime del fotograma, el valor animado se establece inmediatamente en el valor especificado en el Value del fotograma clave. Dado que no hay interpolación, hay un solo fotograma clave que puedes usar en la colección de fotogramas clave ObjectAnimationUsingKeyFrames: DiscreteObjectKeyFrame.

El Value de un DiscreteObjectKeyFrame, por lo general, se establece con una sintaxis de elementos de propiedades, ya que el valor del objeto que intentas establecer a menudo no se expresa como una cadena para rellenar el Value en una sintaxis de atributos. También puedes usar la sintaxis de atributos si usas una referencia como StaticResource.

Un lugar en el que verás que se usa ObjectAnimationUsingKeyFrames en las plantillas predeterminadas es cuando una propiedad de la 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 del tipo Brush como TextBlock.Foreground y no necesitan usar selección indirecta. Pero, dado que SolidColorBrush no es Double, Point ni Color, debes usar ObjectAnimationUsingKeyFrames para poder 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 puedes usar ObjectAnimationUsingKeyFrames para animar propiedades que usan un valor de enumeración. Aquí tienes otro ejemplo de un estilo con nombre procedente de las plantillas predeterminadas de Windows en tiempo de ejecución. Observa que se establece la propiedad Visibility que toma una constante de enumeración de Visibility. En este caso, puedes establecer el valor con la sintaxis de atributos. Solo necesitas el nombre de constante no completo de una enumeración para establecer 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 usar más de un DiscreteObjectKeyFrame para un conjunto de fotogramas ObjectAnimationUsingKeyFrames. Esta puede ser una forma interesante de crear una animación de presentación al animar el valor de Image.Source, como un escenario de ejemplo para el cual varios valores de objetos pueden resultar útiles.

Temas relacionados

Guía básica para crear aplicaciones con C#, C++ o VB
Sintaxis de property-path
Introducción a las propiedades de dependencia
Storyboard
Storyboard.TargetProperty

 

 

Mostrar:
© 2015 Microsoft