Funciones de aceleración

Las funciones de aceleración le permiten aplicar fórmulas matemáticas personalizadas a las animaciones. Por ejemplo, puede que quiera que un objeto rebote de forma realista o se comporte como si estuviera sobre un muelle. Podría usar animaciones de fotogramas clave o incluso animaciones From/To/By para aproximarse a estos efectos pero supondría bastante trabajo y la animación sería menos precisa que si usa un fórmula matemática.

Además de crear su propia función de aceleración personalizada heredada de EasingFunctionBase, puede usar una de las muchas funciones de aceleración proporcionadas por el entorno de ejecución para crear efectos comunes.

  • BackEase: retira el movimiento de una animación un poco antes de que comience en la ruta indicada.

  • BounceEase: crea un efecto de rebote.

  • CircleEase: crea una animación que se acelera o desacelera con una función circular.

  • CubicEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t3.

  • ElasticEase: crea una animación que se asemeja a un muelle que oscila de arriba abajo hasta detenerse.

  • ExponentialEase: crea una animación que se acelera o desacelera con una fórmula exponencial.

  • PowerEase: crea una animación que aumenta o disminuye la velocidad usando la fórmula f(t) = tp, donde p es igual al valor de la propiedad Power.

  • QuadraticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t2.

  • QuarticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t4.

  • QuinticEase: crea una animación que se acelera o desacelera con la fórmula f(t) = t5.

  • SineEase: crea una animación que se acelera o desacelera con una fórmula senoidal.

Para aplicar una función de aceleración a una animación, use la propiedad EasingFunction de la animación que especifique la función de aceleración que quiera aplicar. El ejemplo siguiente aplica una función de aceleración BounceEase a DoubleAnimation para crear un efecto de rebote.

<Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseDown">
            <BeginStoryboard>
                <Storyboard>
                    <Storyboard x:Name="myStoryboard">
                        <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                         Storyboard.TargetName="myRectangle" 
                         Storyboard.TargetProperty="Height">
                            <DoubleAnimation.EasingFunction>
                                <BounceEase Bounces="2" EasingMode="EaseOut" 
                                 Bounciness="2" />
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

En el ejemplo anterior, la función de aceleración se aplicó a una animación From/To/By. También puede aplicar estas funciones de aceleración a animaciones de fotogramas clave. En el ejemplo siguiente se muestra cómo usar fotogramas clave con funciones de aceleración asociadas a ellos para crear una animación de un rectángulo que se contrae hacia arriba, se ralentiza, se expande hacia abajo (como si cayera) y luego rebota hasta detenerse.

<Rectangle Name="myRectangle" Width="200" Height="200" Fill="Blue">
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseDown">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames
                     Storyboard.TargetProperty="Height"
                     Storyboard.TargetName="myRectangle">

                        <!-- This keyframe animates the ellipse up to the crest 
                             where it slows down and stops. -->
                        <EasingDoubleKeyFrame Value="30" KeyTime="00:00:02">
                            <EasingDoubleKeyFrame.EasingFunction>
                                <CubicEase EasingMode="EaseOut"/>
                            </EasingDoubleKeyFrame.EasingFunction>
                        </EasingDoubleKeyFrame>

                        <!-- This keyframe animates the ellipse back down and makes
                             it bounce. -->
                        <EasingDoubleKeyFrame Value="200" KeyTime="00:00:06">
                            <EasingDoubleKeyFrame.EasingFunction>
                                <BounceEase Bounces="5" EasingMode="EaseOut"/>
                            </EasingDoubleKeyFrame.EasingFunction>
                        </EasingDoubleKeyFrame>

                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>

</Rectangle>

Puede usar la propiedad EasingMode para alterar como se comporta la función de aceleración, es decir, cambiar cómo interpola la animación. Existen tres posibles valores que se pueden otorgar a EasingMode:

  • EaseIn: la interpolación sigue la fórmula matemática asociada a la función de aceleración.

  • EaseOut: la interpolación es una interpolación al 100 % menos el resultado de la fórmula asociada a la función de aceleración.

  • EaseInOut: la interpolación utiliza EaseIn para la primera la mitad de la animación y EaseOut para la segunda mitad.

Los gráficos siguientes muestran los distintos valores de EasingMode, donde f(x) representa el progreso de la animación y t representa el tiempo.

BackEase

Gráficos EasingMode para BackEase

BounceEase

Gráficos EasingMode para BounceEase

CircleEase

Gráficos EasingMode para CircleEase

CubicEase

Gráficos EasingMode para CubicEase

ElasticEase

ElasticEase con gráficos de diferentes EasingMode

ExponentialEase

Gráficos ExponentialEase de diferentes EasingMode

PowerEase

QuarticEase con gráficos de diferentes EasingMode

QuadraticEase

QuadraticEase con gráficos de diferentes easingmodes

QuarticEase

QuarticEase con gráficos de diferentes EasingMode

QuinticEase

QuinticEase con gráficos de diferentes easingmodes

SineEase

SineEase para diferentes valores de EasingMode

Nota

Puede usar PowerEase para crear el mismo comportamiento que CubicEase, QuadraticEase, QuarticEase y QuinticEase mediante la propiedad Power. Por ejemplo, si quiere usar PowerEase para substituir CubicEase, especifique un valor Power de 3.

Además de usar las funciones de aceleración incluidas en el tiempo de ejecución, puede crear sus propias funciones de aceleración heredadas de EasingFunctionBase. En el ejemplo siguiente se muestra cómo crear una función de aceleración simple personalizada. Puede añadir su propia lógica matemática para determinar cómo se comporta la función de aceleración al reemplazar el método EaseInCore.

namespace CustomEasingFunction
{
    public class CustomSeventhPowerEasingFunction : EasingFunctionBase
    {
        public CustomSeventhPowerEasingFunction()
            : base()
        {
        }

        // Specify your own logic for the easing function by overriding
        // the EaseInCore method. Note that this logic applies to the "EaseIn"
        // mode of interpolation.
        protected override double EaseInCore(double normalizedTime)
        {
            // applies the formula of time to the seventh power.
            return Math.Pow(normalizedTime, 7);
        }

        // Typical implementation of CreateInstanceCore
        protected override Freezable CreateInstanceCore()
        {

            return new CustomSeventhPowerEasingFunction();
        }
    }
}
Namespace CustomEasingFunction
    Public Class CustomSeventhPowerEasingFunction
        Inherits EasingFunctionBase
        Public Sub New()
            MyBase.New()
        End Sub

        ' Specify your own logic for the easing function by overriding
        ' the EaseInCore method. Note that this logic applies to the "EaseIn"
        ' mode of interpolation. 
        Protected Overrides Function EaseInCore(ByVal normalizedTime As Double) As Double
            ' applies the formula of time to the seventh power.
            Return Math.Pow(normalizedTime, 7)
        End Function

        ' Typical implementation of CreateInstanceCore
        Protected Overrides Function CreateInstanceCore() As Freezable

            Return New CustomSeventhPowerEasingFunction()
        End Function

    End Class
End Namespace
<Window x:Class="CustomEasingFunction.Window1"
        xmlns:CustomEase="clr-namespace:CustomEasingFunction"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="500" Width="300">
    <StackPanel>
        <TextBlock Margin="10" TextWrapping="Wrap">Click on the rectangle to start the animation</TextBlock>
        <StackPanel x:Name="LayoutRoot" Background="White">

            <Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">
                <Rectangle.Triggers>
                    <EventTrigger RoutedEvent="Rectangle.MouseDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation From="30" To="300" Duration="00:00:3" 
                                 Storyboard.TargetName="myRectangle" 
                                 Storyboard.TargetProperty="Height">
                                    <DoubleAnimation.EasingFunction>

                                        <!-- You get the EasingMode property for free on your custom
                                             easing function.-->
                                        <CustomEase:CustomSeventhPowerEasingFunction EasingMode="EaseIn"/>
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Rectangle.Triggers>

            </Rectangle>

        </StackPanel>
    </StackPanel>

</Window>