缓动函数

缓动函数允许将自定义的数学公式应用到动画。 例如,用户可能希望某个对象逼真地弹跳或表现出像在弹簧上一样。 可使用关键帧甚至 From/To/By 动画来近似地实现这些效果,但它将需要大量工作,并且动画不如使用数学公式准确。

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

  • BackEase:动画开始在指定路径上运动前稍微收缩动画的运行。

  • BounceEase:创建弹跳效果。

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

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

  • ElasticEase:创建一个动画,模拟弹簧的来回振荡运动,直到它达到停止状态。

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

  • PowerEase:使用公式 f(t) = tp 创建加速和/或减速的动画,其中 p 等于 Power 属性

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

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

  • QuinticEase:使用公式 f(t) = 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 动画。 还可以将这些缓动函数应用到关键帧动画。 以下示例显示如何将关键帧与其相关联的缓动函数结合使用,以创建一个协定上升、减速、向下展开(如同下落),然后弹跳至停止的矩形的动画。

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

BounceEase

BounceEase EasingMode graphs.

CircleEase

CircleEase EasingMode graphs.

CubicEase

CubicEase EasingMode graphs.

ElasticEase

ElasticEase with graphs of different easingmodes.

ExponentialEase

ExponentialEase graphs of different easingmodes.

PowerEase

QuarticEase with graphs of different easingmodes.

QuadraticEase

QuadraticEase with graphs of different easingmodes

QuarticEase

QuarticEase with graphs of different easingmodes.

QuinticEase

QuinticEase with graphs of different easingmodes.

SineEase

SineEase for different EasingMode values

注意

可使用 PowerEase 通过 Power 属性创建与 CubicEaseQuadraticEaseQuarticEaseQuinticEase 相同的行为。 例如,如果要使用 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>