Функции плавности
Функции плавности позволяют применять к анимациям настраиваемые математические формулы. Например, может потребоваться, чтобы объект реалистично подпрыгивал или вел себя так, будто он на пружине. Можно было бы воспользоваться анимацией по полным кадрам или даже анимацией 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.
Примечание |
---|
Можно использовать PowerEase для создания того же поведения, что и CubicEase, QuadraticEase, QuarticEase и QuinticEase с помощью свойства Power.Например, если планируется использовать PowerEase для подстановки CubicEase, следует указать значение свойства Power, равное 3. |
Кроме использования функций округления, включенных в среду выполнения, можно создавать собственные функции округления, наследуя от EasingFunctionBase. В следующем примере показывается создание простой пользовательской функции округления. Можно добавить собственную математическую логику для поведения функции округления, переопределив метод EaseInCore.
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
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();
}
}
}
<Window x:Class="CustomEasingFunction.Window1"
xmlns:CustomEase="clr-namespace:CustomEasingFunction"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>