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.
Gráficos EasingMode para BackEaseBackEase_Graph
Gráficos EasingMode para BounceEaseBounceEase_Graph
Gráficos EasingMode para CircleEaseCircleEase_Graph
Gráficos EasingMode para CubicEaseCubicEase_Graph
ElasticEase con gráficos de diferentes EasingModeElasticEase_Graph
Gráficos ExponentialEase de diferentes EasingModeExponentialEase_Graph
QuarticEase con gráficos de diferentes EasingModeQuarticEase_Graph
QuadraticEase con gráficos de diferentes easingmodesQuadraticEase_Graph
QuarticEase con gráficos de diferentes EasingModeQuarticEase_Graph
QuinticEase con gráficos de diferentes easingmodesQuinticEase_Graph
SineEase para diferentes valores de EasingModeSineEase_Graph
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>
.NET Desktop feedback