Animaciones de fotograma clave y animaciones de función de aceleraciónKey-frame animations and easing function animations

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 guion 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.Linear key-frame animations, key-frame animations with a KeySpline value, or easing functions are three different techniques for approximately the same scenario: creating a storyboarded animation that's a bit more complex, and that uses a nonlinear animation behavior from a starting state to an end state.

Requisitos previosPrerequisites

Asegúrate de que has leído el tema sobre las animaciones de guion gráfico.Make sure you've read the Storyboarded animations topic. Este tema se basa en los conceptos de animación que se explicaron en el tema sobre animaciones de guion gráfico y no los explicaremos nuevamente.This topic builds on the animation concepts that were explained in Storyboarded animations and won't go over them again. Por ejemplo, en la sección de animaciones de guion 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.For example, Storyboarded animations describes how to target animations, storyboards as resources, the Timeline property values such as Duration, FillBehavior, and so on.

Animación mediante animaciones de fotograma claveAnimating using key-frame animations

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.Key-frame animations permit more than one target value that is reached at a point along the animation timeline. 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.In other words, each key frame can specify a different intermediate value, and the last key frame reached is the final animation value. Si especificas varios valores para animar, puedes crear animaciones más complejas.By specifying multiple values to animate, you can make more complex animations. 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.Key-frame animations also enable different interpolation logic, which are each implemented as a different KeyFrame subclass per animation type. 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.Specifically, each key-frame animation type has a Discrete, Linear, Spline and Easing variation of its KeyFrame class for specifying its key frames. 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.For example, to specify an animation that targets a Double and uses key frames, you could declare key frames with DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame, and 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.You can use any and all of these types within a single KeyFrames collection, to change the interpolation each time a new key frame is reached.

En el caso del comportamiento de interpolación, cada fotograma clave controla la interpolación hasta que se alcanza el tiempo KeyTime.For interpolation behavior, each key frame controls the interpolation until its KeyTime time is reached. En ese momento también se alcanza su Value.Its Value is reached at that time also. 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.If there are more key frames beyond, the value then becomes the starting value for the next key frame in a sequence.

Al inicio de la animación, si no existe ningún fotograma clave con un elemento KeyTime con el valor "0:0:0", el valor inicial es igual al valor no animado de la propiedad.At the start of the animation, if no key frame with KeyTime of "0:0:0" exists, the starting value is whatever the non-animated value of the property is. Esto es similar al modo en que la animación de / a / by actúa si no hay ningún de.This is similar to how a From/To/By animation acts if there is no From.

De forma implícita, la duración de una animación de fotograma clave es la duración del valor más alto de KeyTime establecido en cualquiera de los fotogramas clave.The duration of a key-frame animation is implicitly the duration equal to the highest KeyTime value set in any of its key frames. Si quieres, puedes configurar un valor de Duration explícito, pero recuerda que no puede ser menor que el valor KeyTime de tus propios fotogramas clave; de lo contrario, cortarás parte de la animación.You can set an explicit Duration if you want, but be careful it's not shorter than a KeyTime in your own key frames or you'll cut off part of the animation.

Además de la duración, puede establecer todas las propiedades basadas en la escala de tiempo en una animación de fotogramas clave, como puede hacerlo con una animación de / a / by , ya que las clases de animación de fotogramas clave también derivan de la escala de tiempo.In addition to Duration, you can set all the Timeline based properties on a key-frame animation, like you can with a From/To/By animation, because the key-frame animation classes also derive from Timeline. Son las siguientes:These are:

  • AutoReverse: una vez que se alcanza el último fotograma clave, los fotogramas se repiten en orden inverso desde el final.AutoReverse: once the last key frame is reached, the frames are repeated in reverse order from the end. Esto duplica la duración aparente de la animación.This doubles the apparent duration of the animation.
  • BeginTime: retrasa el inicio de la animación.BeginTime: delays the start of the animation. La escala de tiempo para los valores KeyTime de los fotogramas no inicia el recuento hasta que se alcanza BeginTime, de modo que no hay riesgo de cortar los fotogramas.The timeline for the KeyTime values in the frames doesn't start counting until BeginTime is reached, so there's no risk of cutting off frames
  • FillBehavior: controla lo que sucede cuando se llega al último fotograma clave.FillBehavior: controls what happens when the last key frame is reached. FillBehavior no tiene ningún efecto en los fotogramas clave intermedios.FillBehavior has no effect on any intermediate key frames.
  • RepeatBehavior:RepeatBehavior:
    • si está establecido como Forever, los fotogramas clave y sus escalas de tiempo se repiten de manera indefinida.If set to Forever, then the key frames and their timeline repeat infinitely.
    • Si está establecido como un recuento de iteraciones, la escala de tiempo se repite esa cantidad de veces.If set to an iteration count, the timeline repeats that many times.
    • Si está establecido como un valor de Duration, la escala de tiempo se repite hasta llegar a dicho horario.If set to a Duration, the timeline repeats until that time is reached. 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.This might truncate the animation part way through the key frame sequence, if it's not an integer factor of the timeline's implicit duration.
  • SpeedRatio (no se usa con frecuencia)SpeedRatio (not commonly used)

Fotogramas clave linealesLinear key frames

Los fotogramas clave lineales dan como resultado una interpolación lineal simple del valor hasta que se alcanza el valor KeyTime del fotograma.Linear key frames result in a simple linear interpolation of the value until the frame's KeyTime is reached. Este comportamiento de interpolación es el más similar al más sencillo delas / To / animaciones que se describen en el tema sobre animaciones con guiones gráficos .ByThis interpolation behavior is the most similar to the simpler From/To/By animations described in the Storyboarded animations topic.

Aquí te mostramos cómo usar una animación de fotograma clave para escalar el alto de un rectángulo con fotogramas clave lineales.Here's how to use a key-frame animation to scale the render height of a rectangle, using linear key frames. 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.This example runs an animation where the height of the rectangle increases slightly and linearly for the first 4 seconds, then scales rapidly for the last second until the rectangle is double the starting height.

<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 discretosDiscrete key frames

Los fotogramas clave discretos no usan ninguna interpolación.Discrete key frames don't use any interpolation at all. Cuando se llega a un valor KeyTime, simplemente se aplica el nuevo Value.When a KeyTime is reached, the new Value is simply applied. Según la propiedad de interfaz de usuario que se está animando, por lo general, esto genera una animación que simula un "salto".Depending on which UI property is being animated, this often produces an animation that appears to "jump". Asegúrate de que este sea el comportamiento estético que realmente quieres.Be certain that this is the aesthetic behavior that you really want. 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.You can minimize the apparent jumps by increasing the number of key frames you declare, but if a smooth animation is your goal, you might be better off using linear or spline key frames instead.

Nota

Los fotogramas clave discretos son la única manera de animar un valor que no es de tipo Double, Pointy color, con un DiscreteObjectKeyFrame.Discrete key frames are the only way to animate a value that isn't of type Double, Point, and Color, with a DiscreteObjectKeyFrame. Analizaremos esto en mayor detalle más adelante en este tema.We'll discuss this in more detail later in this topic.

Fotogramas clave splineSpline key frames

Un fotograma clave spline crea una transición variable entre los valores según el valor de la propiedad KeySpline .A spline key frame creates a variable transition between values according to the value of the KeySpline property. 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.This property specifies the first and second control points of a Bezier curve, which describes the acceleration of the animation. Básicamente, un KeySpline define una relación de función a tiempo en la que el gráfico de tiempo de función es la forma de esa curva de Bézier.Basically, a KeySpline defines a function-over-time relationship where the function-time graph is the shape of that Bezier curve. Normalmente, se especifica un valor de KeySpline en una cadena de atributo abreviado XAML que tiene cuatro valores Double separados por espacios o comas.You typically specify a KeySpline value in a XAML shorthand attribute string that has four Double values separated by spaces or commas. Estos valores son pares "X,Y" para dos puntos de control de la curva Bézier.These values are "X,Y" pairs for two control points of the Bezier curve. X representa al tiempo e Y es el modificador de función para el valor."X" is time and "Y" is the function modifier to the value. Cada valor debe estar comprendido siempre entre 0 y 1, ambos inclusive.Each value should always be between 0 and 1 inclusive. Sin una modificación del punto de control a un valor 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.Without control point modification to a KeySpline, the straight line from 0,0 to 1,1 is the representation of a function over time for a linear interpolation. 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.Your control points change the shape of that curve and thus the behavior of the function over time for the spline animation. Lo mejor es verlo en un gráfico.It's probably best to see this visually as a graph. 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 KeySpline.You can run the Silverlight key-spline visualizer sample in a browser to see how the control points modify the curve and how a sample animation runs when using it as a KeySpline value.

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).This next example shows three different key frames applied to an animation, with the last one being a key spline animation for a Double value (SplineDoubleKeyFrame). Observa la cadena "0.6,0.0 0.9,0.00" que se aplica a KeySpline.Note the string "0.6,0.0 0.9,0.00" applied for KeySpline. Esta 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 KeyTime.This produces a curve where the animation appears to run slowly at first but then rapidly reaches the value just before the KeyTime is reached.

<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ónEasing key frames

Un fotograma clave de aceleración es un fotograma clave en el que se aplica la interpolación, y la función a lo largo del tiempo de la interpolación se controla mediante varias fórmulas matemáticas predefinidas.An easing key frame is a key frame where interpolation is being applied, and the function over time of the interpolation is controlled by several pre-defined mathematical formulas. En realidad, puede producir prácticamente el mismo resultado con un fotograma clave spline como se puede hacer con algunos de los tipos de función de aceleración, pero también hay algunas funciones de aceleración, como la aceleración, que no se pueden reproducir con una spline.You can actually produce much the same result with a spline key frame as you can with some of the easing function types, but there are also some easing functions, such as BackEase, that you can't reproduce with a 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.To apply an easing function to an easing key frame, you set the EasingFunction property as a property element in XAML for that key frame. Para el valor, especifica un elemento de objeto para uno de los tipos de funciones de aceleración.For the value, specify an object element for one of the easing function types.

En este ejemplo se aplica CubicEase y, luego, BounceEase como fotogramas clave sucesivos a DoubleAnimation para crear un efecto de rebote.This example applies a CubicEase and then a BounceEase as successive key frames to a DoubleAnimation to create a bouncing effect.

<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.This is just one easing function example. Podrás encontrar más información en la siguiente sección.We'll cover more in the next section.

Funciones de aceleraciónEasing functions

Las funciones de aceleración le permiten aplicar fórmulas matemáticas personalizadas a las animaciones.Easing functions allow you to apply custom mathematical formulas to your animations. 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.Mathematical operations are often useful to produce animations that simulate real-world physics in a 2-D coordinate system. Por ejemplo, puede que quiera que un objeto rebote de forma realista o se comporte como si estuviera sobre un muelle.For example, you may want an object to realistically bounce or behave as though it were on a spring. Puede usar animaciones de fotogramas clave o incluso de / a / por animaciones para aproximar estos efectos, pero tomaría una cantidad significativa de trabajo y la animación sería menos precisa que usar una fórmula matemática.You could use key frame or even From/To/By animations to approximate these effects but it would take a significant amount of work and the animation would be less accurate than using a mathematical formula.

Las funciones de aceleración se pueden aplicar a las animaciones de tres formas:Easing functions can be applied to animations in three ways:

A continuación te indicamos una lista de funciones de aceleración:Here is a list of the easing functions:

  • BackEase: retira el movimiento de una animación un poco antes de que comience dicha animación en la ruta indicada.BackEase: Retracts the motion of an animation slightly before it begins to animate in the path indicated.
  • BounceEase: crea un efecto de rebote.BounceEase: Creates a bouncing effect.
  • CircleEase: crea una animación que se acelera o desacelera con una función circular.CircleEase: Creates an animation that accelerates or decelerates using a circular function.
  • CubicEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t3.CubicEase: Creates an animation that accelerates or decelerates using the formula f(t) = t3.
  • ElasticEase: crea una animación que se asemeja a un muelle que oscila de arriba abajo hasta que se detiene.ElasticEase: Creates an animation that resembles a spring oscillating back and forth until it comes to rest.
  • ExponentialEase: crea una animación que se acelera o desacelera con una fórmula exponencial.ExponentialEase: Creates an animation that accelerates or decelerates using an exponential formula.
  • PowerEase: crea una animación que se acelera o desacelera con la fórmula f(t) = tp, donde p equivale a la propiedad Power.PowerEase: Creates an animation that accelerates or decelerates using the formula f(t) = tp where p is equal to the Power property.
  • QuadraticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t2.QuadraticEase: Creates an animation that accelerates or decelerates using the formula f(t) = t2.
  • QuarticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t4.QuarticEase: Creates an animation that accelerates or decelerates using the formula f(t) = t4.
  • QuinticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t5.QuinticEase: Create an animation that accelerates or decelerates using the formula f(t) = t5.
  • SineEase: crea una animación que se acelera o desacelera con una fórmula senoidal.SineEase: Creates an animation that accelerates or decelerates using a sine formula.

Algunas de las funciones de aceleración tienen sus propias propiedades.Some of the easing functions have their own properties. Por ejemplo, BounceEase tiene dos propiedades Bounces y Bounciness que modifican el comportamiento a lo largo del tiempo de dicha función BounceEase.For example, BounceEase has two properties Bounces and Bounciness that modify the function-over-time behavior of that particular BounceEase. 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.Other easing functions such as CubicEase don't have properties other than the EasingMode property that all easing functions share, and always produce the same function-over-time behavior.

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.Some of these easing functions have a bit of overlap, depending on how you set properties on the easing functions that have properties. Por ejemplo, QuadraticEase es exactamente igual que PowerEase con un valor de Power que equivale a 2.For example, QuadraticEase is exactly the same as a PowerEase with Power equal to 2. Y CircleEase es básicamente un ExponentialEasede valor predeterminado.And CircleEase is basically a default-value ExponentialEase.

La función de aceleración de la aceleración es única, ya que puede cambiar el valor fuera del intervalo normal de acuerdo con / los valores dea o de fotogramas clave.The BackEase easing function is unique because it can change the value outside of the normal range as set by From/To or values of key frames. Inicia la animación cambiando el valor en la dirección opuesta como cabría esperar de un comportamiento normal de / a , vuelve al valor desde o iniciando de nuevo y, a continuación, ejecuta la animación como normal.It starts the animation by changing the value in the opposite direction as would be expected from a normal From/To behavior, goes back to the From or starting value again, and then runs the animation as normal.

En un ejemplo anterior, mostramos cómo declarar una función de aceleración para una animación de fotograma clave.In an earlier example, we showed how to declare an easing function for a key-frame animation. En el siguiente ejemplo se aplica una función de aceleración a una animación de / a / by .This next sample applies an easing function to a From/To/By animation.

<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 entradas y salidas lentas a una animación de / a / by , se cambian las características de función en tiempo de cómo se interpola el valor entre los valores desde y hasta durante la duración de la animación.When an easing function is applied to a From/To/By animation, it's changing the function- over-time characteristics of how the value interpolates between the From and To values over the Duration of the animation. Sin una función de aceleración, se trataría de una interpolación lineal.Without an easing function, that would be a linear interpolation.

Animaciones de valores de objeto discretosDiscrete object value animations

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.One type of animation deserves special mention because it's the only way you can apply an animated value to properties that aren't of type Double, Point, or Color. Se trata de la animación de fotograma clave ObjectAnimationUsingKeyFrames.This is the key-frame animation ObjectAnimationUsingKeyFrames. La animación con valores Object es diferente porque no es posible interpolar los valores entre los fotogramas.Animating using Object values is different because there's no possibility of interpolating the values between the frames. Cuando se alcanza el valor KeyTime del fotograma, el valor animado se establece inmediatamente en el valor especificado en la propiedad Value en el fotograma clave.When the frame's KeyTime is reached, the animated value is immediately set to the value specified in the key frame's Value. Dado que no hay interpolación, solo hay un fotograma clave que se usa en la colección de fotogramas clave de ObjectAnimationUsingKeyFrames : DiscreteObjectKeyFrame.Because there's no interpolation, there's only one key frame you use in the ObjectAnimationUsingKeyFrames key frames collection: DiscreteObjectKeyFrame.

Por lo general, la propiedad Value de la clase DiscreteObjectKeyFrame 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 la propiedad Value en una sintaxis de atributos.The Value of a DiscreteObjectKeyFrame is often set using property element syntax, because the object value you are trying to set often is not expressible as a string to fill Value in attribute syntax. Todavía puede usar la sintaxis de atributo si usa una referencia como StaticResource.You can still use attribute syntax if you use a reference such as StaticResource.

Verás que se usa la clase ObjectAnimationUsingKeyFrames en las plantillas predeterminadas, cuando una propiedad de la plantilla hace referencia a un recurso Brush.One place you'll see an ObjectAnimationUsingKeyFrames used in the default templates is when a template property references a Brush resource. Estos recursos son objetos SolidColorBrush, no solo un valor Color, y usan recursos definidos como temas del sistema (ThemeDictionaries).These resources are SolidColorBrush objects, not just a Color value, and they use resources that are defined as system themes (ThemeDictionaries). Se pueden asignar directamente a un valor del tipo Brush como TextBlock.Foreground y no necesitan usar selección indirecta.They can be assigned directly to a Brush-type value such as TextBlock.Foreground and don't need to use indirect targeting. Pero, dado que SolidColorBrush no es Double, Point ni Color, debes usar ObjectAnimationUsingKeyFrames para poder usar el recurso.But because a SolidColorBrush is not Double, Point, or Color, you have to use a ObjectAnimationUsingKeyFrames to use the resource.

<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.You also might use ObjectAnimationUsingKeyFrames to animate properties that use an enumeration value. Aquí tienes otro ejemplo de un estilo con nombre procedente de las plantillas predeterminadas de Windows Runtime.Here's another example from a named style that comes from the Windows Runtime default templates. Observa que se establece la propiedad Visibility que toma una constante de enumeración de Visibility.Note how it sets the Visibility property that takes a Visibility enumeration constant. En este caso, puedes establecer el valor con la sintaxis de atributos.In this case you can set the value using attribute syntax. 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".You only need the unqualified constant name from an enumeration for setting a property with an enumeration value, for example "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.You can use more than one DiscreteObjectKeyFrame for an ObjectAnimationUsingKeyFrames frame set. 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.This might be an interesting way to create a "slide show" animation by animating the value of Image.Source, as an example scenario for where multiple object values might be useful.