缓动函数

缓动函数允许向动画应用自定义数学公式。 例如,你可能希望某个对象以现实方式弹跳或表现得像是处于弹簧上。 可以使用 Key-Frame 甚至 From/To/By 动画来近似这些效果,但需要大量的工作,动画的准确程度会低于使用数学公式。

除了通过继承 EasingFunctionBase自创建自定义缓动函数之外,还可以使用运行时提供的多个缓动函数之一来创建常见效果。

  • BackEase:在动画开始沿指示的路径执行之前,稍微回缩动画的动作。

  • BounceEase:创建弹跳效果。

  • CircleEase:创建使用循环函数加速和/或减速的动画。

  • CubicEase:使用公式 ft) = t3 创建加速和/或减速的动画。

  • ElasticEase:创建一个类似于弹簧来回振荡直到静止的动画。

  • ExponentialEase:创建使用指数公式加速和/或减速的动画。

  • PowerEase:创建一个动画,该动画使用公式 ft) = tp 加速和/或减速,其中 p 等于 Power 属性。

  • QuadraticEase:使用公式 ft) = t2 创建加速和/或减速的动画。

  • QuarticEase:使用公式 ft) = t4 创建加速和/或减速的动画。

  • QuinticEase:使用公式 ft) = t5 创建加速和/或减速的动画。

  • SineEase:创建使用正弦公式加速和/或减速的动画。

若要将缓动函数应用于动画,请使用 EasingFunction 动画的属性指定要应用于动画的缓动函数。 以下示例将 BounceEase 缓动函数应用于 DoubleAnimation 创建弹跳效果。

<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>

在前面的示例中,缓动函数应用于 From/To/By 动画。 还可以将这些缓动函数应用于 Key-Frame 动画。 下面的示例演示如何使用与它们关联的缓动函数的关键帧来创建一个矩形的动画,该矩形向上收缩、放慢速度、向下展开(好像下降),然后弹跳到停止。

<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>

可以使用该 EasingMode 属性来更改缓动函数的行为方式,即更改动画内插的方式。 你可以为 EasingMode 设定三个可能的值如下:

  • EaseIn:内插遵循与缓动函数关联的数学公式。

  • EaseOut:插值遵循 100% 插值并减去与缓动函数相关的公式输出。

  • EaseInOut:插值在动画的前半部分使用EaseIn,在后半部分使用EaseOut

下面的图展示了EasingMode的不同值,其中f(x) 表示动画进度,t 表示时间。

BackEase

BackEase EasingMode 图形。

BounceEase

BounceEase EasingMode 图形。

CircleEase

CircleEase 缓动模式图表。

CubicEase

CubicEase EasingMode 图形。

ElasticEase

具有不同缓动模式的图形的 ElasticEase。

ExponentialEase

不同类型缓动模式下的 ExponentialEase 曲线图。

PowerEase

不同缓释模式的 QuarticEase 图形。

QuadraticEase

不同缓动模式的二次缓动图表

QuarticEase

不同缓动模式的 QuarticEase 图形。

QuinticEase

QuinticEase 包含不同缓动模式的图表。

SineEase

用于不同 EasingMode 值的 SineEase

注释

可以使用PowerEase属性来创建与CubicEaseQuadraticEaseQuarticEaseQuinticEase相同的行为,使用Power属性。 例如,如果要用于 PowerEase 替换 CubicEase,请指定 Power 值 3。

除了使用运行时中包含的缓动函数之外,还可以通过继承自 EasingFunctionBase来创建自己的自定义缓动函数。 以下示例演示如何创建简单的自定义缓动函数。 可以通过重写 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>