Created
May 16, 2016 19:27
-
-
Save jmlyn/fb21cb63ded54866f0d650210ab0316b to your computer and use it in GitHub Desktop.
Robert Penner's easing equations, source: http://robertpenner.com/easing/, original author: Darren David, all rights reserved by original authors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * PennerDoubleAnimation | |
| * Animates the value of a double property between two target values using | |
| * Robert Penner's easing equations for interpolation over a specified Duration. | |
| * | |
| * @author Darren David darren-code@lookorfeel.com | |
| * @version 1.0 | |
| * | |
| * Credit/Thanks: | |
| * Robert Penner - The easing equations we all know and love | |
| * (http://robertpenner.com/easing/) [See License.txt for license info] | |
| * | |
| * Lee Brimelow - initial port of Penner's equations to WPF | |
| * (http://thewpfblog.com/?p=12) | |
| * | |
| * Zeh Fernando - additional equations (out/in) from | |
| * caurina.transitions.Tweener (http://code.google.com/p/tweener/) | |
| * [See License.txt for license info] | |
| */ | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Diagnostics; | |
| using System.Reflection; | |
| using System.Text; | |
| using System.Windows; | |
| using System.Windows.Media.Animation; | |
| using System.ComponentModel; | |
| using System.Globalization; | |
| namespace LookOrFeel.Animation | |
| { | |
| /// <summary> | |
| /// Animates the value of a double property between two target values using | |
| /// Robert Penner's easing equations for interpolation over a specified Duration. | |
| /// </summary> | |
| /// <example> | |
| /// <code> | |
| /// // C# | |
| /// PennerDoubleAnimation anim = new PennerDoubleAnimation(); | |
| /// anim.Type = PennerDoubleAnimation.Equations.Linear; | |
| /// anim.From = 1; | |
| /// anim.To = 0; | |
| /// myControl.BeginAnimation( OpacityProperty, anim ); | |
| /// | |
| /// // XAML | |
| /// <Storyboard x:Key="AnimateXamlRect"> | |
| /// <animation:PennerDoubleAnimation | |
| /// Storyboard.TargetName="myControl" | |
| /// Storyboard.TargetProperty="(Canvas.Left)" | |
| /// From="0" | |
| /// To="600" | |
| /// Equation="BackEaseOut" | |
| /// Duration="00:00:05" /> | |
| /// </Storyboard> | |
| /// | |
| /// <Control.Triggers> | |
| /// <EventTrigger RoutedEvent="FrameworkElement.Loaded"> | |
| /// <BeginStoryboard Storyboard="{StaticResource AnimateXamlRect}"/> | |
| /// </EventTrigger> | |
| /// </Control.Triggers> | |
| /// </code> | |
| /// </example> | |
| public class PennerDoubleAnimation : DoubleAnimationBase | |
| { | |
| /// <summary> | |
| /// Enumeration of all easing equations. | |
| /// </summary> | |
| public enum Equations | |
| { | |
| Linear, | |
| QuadEaseOut, QuadEaseIn, QuadEaseInOut, QuadEaseOutIn, | |
| ExpoEaseOut, ExpoEaseIn, ExpoEaseInOut, ExpoEaseOutIn, | |
| CubicEaseOut, CubicEaseIn, CubicEaseInOut, CubicEaseOutIn, | |
| QuartEaseOut, QuartEaseIn, QuartEaseInOut, QuartEaseOutIn, | |
| QuintEaseOut, QuintEaseIn, QuintEaseInOut, QuintEaseOutIn, | |
| CircEaseOut, CircEaseIn, CircEaseInOut, CircEaseOutIn, | |
| SineEaseOut, SineEaseIn, SineEaseInOut, SineEaseOutIn, | |
| ElasticEaseOut, ElasticEaseIn, ElasticEaseInOut, ElasticEaseOutIn, | |
| BounceEaseOut, BounceEaseIn, BounceEaseInOut, BounceEaseOutIn, | |
| BackEaseOut, BackEaseIn, BackEaseInOut, BackEaseOutIn | |
| } | |
| #region Fields | |
| private MethodInfo _EasingMethod; | |
| #endregion | |
| #region Dependency Properties | |
| public static readonly DependencyProperty EquationProperty = | |
| DependencyProperty.Register( | |
| "Equation", typeof( Equations ), typeof( PennerDoubleAnimation ), | |
| new PropertyMetadata( Equations.Linear, new PropertyChangedCallback( HandleEquationChanged ) ) ); | |
| public static readonly DependencyProperty FromProperty = | |
| DependencyProperty.Register( | |
| "From", typeof( double ), typeof( PennerDoubleAnimation ), new PropertyMetadata( 0.0 ) ); | |
| public static readonly DependencyProperty ToProperty = | |
| DependencyProperty.Register( | |
| "To", typeof( double ), typeof( PennerDoubleAnimation ), new PropertyMetadata( 0.0 ) ); | |
| #endregion | |
| #region Constructors | |
| public PennerDoubleAnimation() | |
| { | |
| } | |
| public PennerDoubleAnimation( Equations type, double from, double to ) | |
| { | |
| Equation = type; | |
| From = from; | |
| To = to; | |
| } | |
| public PennerDoubleAnimation( Equations type, double from, double to, Duration duration ) | |
| { | |
| Equation = type; | |
| From = from; | |
| To = to; | |
| Duration = duration; | |
| } | |
| #endregion | |
| #region Abstract Member Implementations | |
| protected override double GetCurrentValueCore( double startValue, double targetValue, AnimationClock clock ) | |
| { | |
| try | |
| { | |
| // might be able to speed this up by caching it, but who knows | |
| object[] methodParams = new object[4] { clock.CurrentTime.Value.TotalSeconds, From, To - From, Duration.TimeSpan.TotalSeconds }; | |
| return ( double ) _EasingMethod.Invoke( this, methodParams ); | |
| } | |
| catch | |
| { | |
| return From; | |
| } | |
| } | |
| protected override Freezable CreateInstanceCore() | |
| { | |
| return new PennerDoubleAnimation(); | |
| } | |
| #endregion | |
| #region Equations | |
| // These methods are all public to enable reflection in GetCurrentValueCore. | |
| #region Linear | |
| /// <summary> | |
| /// Easing equation function for a simple linear tweening, with no easing. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double Linear( double t, double b, double c, double d ) | |
| { | |
| return c * t / d + b; | |
| } | |
| #endregion | |
| #region Expo | |
| /// <summary> | |
| /// Easing equation function for an exponential (2^t) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ExpoEaseOut( double t, double b, double c, double d ) | |
| { | |
| return ( t == d ) ? b + c : c * ( -Math.Pow( 2, -10 * t / d ) + 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for an exponential (2^t) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ExpoEaseIn( double t, double b, double c, double d ) | |
| { | |
| return ( t == 0 ) ? b : c * Math.Pow( 2, 10 * ( t / d - 1 ) ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for an exponential (2^t) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ExpoEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( t == 0 ) | |
| return b; | |
| if ( t == d ) | |
| return b + c; | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * Math.Pow( 2, 10 * ( t - 1 ) ) + b; | |
| return c / 2 * ( -Math.Pow( 2, -10 * --t ) + 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for an exponential (2^t) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ExpoEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return ExpoEaseOut( t * 2, b, c / 2, d ); | |
| return ExpoEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Circular | |
| /// <summary> | |
| /// Easing equation function for a circular (sqrt(1-t^2)) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CircEaseOut( double t, double b, double c, double d ) | |
| { | |
| return c * Math.Sqrt( 1 - ( t = t / d - 1 ) * t ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a circular (sqrt(1-t^2)) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CircEaseIn( double t, double b, double c, double d ) | |
| { | |
| return -c * ( Math.Sqrt( 1 - ( t /= d ) * t ) - 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a circular (sqrt(1-t^2)) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CircEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return -c / 2 * ( Math.Sqrt( 1 - t * t ) - 1 ) + b; | |
| return c / 2 * ( Math.Sqrt( 1 - ( t -= 2 ) * t ) + 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a circular (sqrt(1-t^2)) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CircEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return CircEaseOut( t * 2, b, c / 2, d ); | |
| return CircEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Quad | |
| /// <summary> | |
| /// Easing equation function for a quadratic (t^2) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuadEaseOut( double t, double b, double c, double d ) | |
| { | |
| return -c * ( t /= d ) * ( t - 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quadratic (t^2) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuadEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c * ( t /= d ) * t + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quadratic (t^2) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuadEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * t * t + b; | |
| return -c / 2 * ( ( --t ) * ( t - 2 ) - 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quadratic (t^2) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuadEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return QuadEaseOut( t * 2, b, c / 2, d ); | |
| return QuadEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Sine | |
| /// <summary> | |
| /// Easing equation function for a sinusoidal (sin(t)) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double SineEaseOut( double t, double b, double c, double d ) | |
| { | |
| return c * Math.Sin( t / d * ( Math.PI / 2 ) ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a sinusoidal (sin(t)) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double SineEaseIn( double t, double b, double c, double d ) | |
| { | |
| return -c * Math.Cos( t / d * ( Math.PI / 2 ) ) + c + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a sinusoidal (sin(t)) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double SineEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * ( Math.Sin( Math.PI * t / 2 ) ) + b; | |
| return -c / 2 * ( Math.Cos( Math.PI * --t / 2 ) - 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a sinusoidal (sin(t)) easing in/out: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double SineEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return SineEaseOut( t * 2, b, c / 2, d ); | |
| return SineEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Cubic | |
| /// <summary> | |
| /// Easing equation function for a cubic (t^3) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CubicEaseOut( double t, double b, double c, double d ) | |
| { | |
| return c * ( ( t = t / d - 1 ) * t * t + 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a cubic (t^3) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CubicEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c * ( t /= d ) * t * t + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a cubic (t^3) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CubicEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * t * t * t + b; | |
| return c / 2 * ( ( t -= 2 ) * t * t + 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a cubic (t^3) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double CubicEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return CubicEaseOut( t * 2, b, c / 2, d ); | |
| return CubicEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Quartic | |
| /// <summary> | |
| /// Easing equation function for a quartic (t^4) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuartEaseOut( double t, double b, double c, double d ) | |
| { | |
| return -c * ( ( t = t / d - 1 ) * t * t * t - 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quartic (t^4) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuartEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c * ( t /= d ) * t * t * t + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quartic (t^4) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuartEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * t * t * t * t + b; | |
| return -c / 2 * ( ( t -= 2 ) * t * t * t - 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quartic (t^4) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuartEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return QuartEaseOut( t * 2, b, c / 2, d ); | |
| return QuartEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Quintic | |
| /// <summary> | |
| /// Easing equation function for a quintic (t^5) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuintEaseOut( double t, double b, double c, double d ) | |
| { | |
| return c * ( ( t = t / d - 1 ) * t * t * t * t + 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quintic (t^5) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuintEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c * ( t /= d ) * t * t * t * t + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quintic (t^5) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuintEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * t * t * t * t * t + b; | |
| return c / 2 * ( ( t -= 2 ) * t * t * t * t + 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a quintic (t^5) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double QuintEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return QuintEaseOut( t * 2, b, c / 2, d ); | |
| return QuintEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Elastic | |
| /// <summary> | |
| /// Easing equation function for an elastic (exponentially decaying sine wave) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ElasticEaseOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d ) == 1 ) | |
| return b + c; | |
| double p = d * .3; | |
| double s = p / 4; | |
| return ( c * Math.Pow( 2, -10 * t ) * Math.Sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) + c + b ); | |
| } | |
| /// <summary> | |
| /// Easing equation function for an elastic (exponentially decaying sine wave) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ElasticEaseIn( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d ) == 1 ) | |
| return b + c; | |
| double p = d * .3; | |
| double s = p / 4; | |
| return -( c * Math.Pow( 2, 10 * ( t -= 1 ) ) * Math.Sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ElasticEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d / 2 ) == 2 ) | |
| return b + c; | |
| double p = d * ( .3 * 1.5 ); | |
| double s = p / 4; | |
| if ( t < 1 ) | |
| return -.5 * ( c * Math.Pow( 2, 10 * ( t -= 1 ) ) * Math.Sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) ) + b; | |
| return c * Math.Pow( 2, -10 * ( t -= 1 ) ) * Math.Sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) * .5 + c + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double ElasticEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return ElasticEaseOut( t * 2, b, c / 2, d ); | |
| return ElasticEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Bounce | |
| /// <summary> | |
| /// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BounceEaseOut( double t, double b, double c, double d ) | |
| { | |
| if ( ( t /= d ) < ( 1 / 2.75 ) ) | |
| return c * ( 7.5625 * t * t ) + b; | |
| else if ( t < ( 2 / 2.75 ) ) | |
| return c * ( 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + .75 ) + b; | |
| else if ( t < ( 2.5 / 2.75 ) ) | |
| return c * ( 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + .9375 ) + b; | |
| else | |
| return c * ( 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + .984375 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BounceEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c - BounceEaseOut( d - t, 0, c, d ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BounceEaseInOut( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return BounceEaseIn( t * 2, 0, c, d ) * .5 + b; | |
| else | |
| return BounceEaseOut( t * 2 - d, 0, c, d ) * .5 + c * .5 + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BounceEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return BounceEaseOut( t * 2, b, c / 2, d ); | |
| return BounceEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #region Back | |
| /// <summary> | |
| /// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: | |
| /// decelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BackEaseOut( double t, double b, double c, double d ) | |
| { | |
| return c * ( ( t = t / d - 1 ) * t * ( ( 1.70158 + 1 ) * t + 1.70158 ) + 1 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: | |
| /// accelerating from zero velocity. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BackEaseIn( double t, double b, double c, double d ) | |
| { | |
| return c * ( t /= d ) * t * ( ( 1.70158 + 1 ) * t - 1.70158 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: | |
| /// acceleration until halfway, then deceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BackEaseInOut( double t, double b, double c, double d ) | |
| { | |
| double s = 1.70158; | |
| if ( ( t /= d / 2 ) < 1 ) | |
| return c / 2 * ( t * t * ( ( ( s *= ( 1.525 ) ) + 1 ) * t - s ) ) + b; | |
| return c / 2 * ( ( t -= 2 ) * t * ( ( ( s *= ( 1.525 ) ) + 1 ) * t + s ) + 2 ) + b; | |
| } | |
| /// <summary> | |
| /// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: | |
| /// deceleration until halfway, then acceleration. | |
| /// </summary> | |
| /// <param name="t">Current time in seconds.</param> | |
| /// <param name="b">Starting value.</param> | |
| /// <param name="c">Final value.</param> | |
| /// <param name="d">Duration of animation.</param> | |
| /// <returns>The correct value.</returns> | |
| public static double BackEaseOutIn( double t, double b, double c, double d ) | |
| { | |
| if ( t < d / 2 ) | |
| return BackEaseOut( t * 2, b, c / 2, d ); | |
| return BackEaseIn( ( t * 2 ) - d, b + c / 2, c / 2, d ); | |
| } | |
| #endregion | |
| #endregion | |
| #region Event Handlers | |
| private static void HandleEquationChanged( object sender, DependencyPropertyChangedEventArgs e ) | |
| { | |
| PennerDoubleAnimation pda = sender as PennerDoubleAnimation; | |
| // cache method so we avoid lookup while animating | |
| pda._EasingMethod = typeof( PennerDoubleAnimation ).GetMethod( e.NewValue.ToString() ); | |
| } | |
| #endregion | |
| #region Properties | |
| /// <summary> | |
| /// The easing equation to use. | |
| /// </summary> | |
| [TypeConverter( typeof( PennerDoubleAnimationTypeConverter ) )] | |
| public Equations Equation | |
| { | |
| get { return ( Equations ) GetValue( EquationProperty ); } | |
| set | |
| { | |
| SetValue( EquationProperty, value ); | |
| // cache method so we avoid lookup while animating | |
| _EasingMethod = this.GetType().GetMethod( value.ToString() ); | |
| } | |
| } | |
| /// <summary> | |
| /// Starting value for the animation. | |
| /// </summary> | |
| public double From | |
| { | |
| get { return ( double ) GetValue( FromProperty ); } | |
| set { SetValue( FromProperty, value ); } | |
| } | |
| /// <summary> | |
| /// Ending value for the animation. | |
| /// </summary> | |
| public double To | |
| { | |
| get { return ( double ) GetValue( ToProperty ); } | |
| set { SetValue( ToProperty, value ); } | |
| } | |
| #endregion | |
| } | |
| public class PennerDoubleAnimationTypeConverter : TypeConverter | |
| { | |
| public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType ) | |
| { | |
| return sourceType == typeof( string ); | |
| } | |
| public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType ) | |
| { | |
| return destinationType == typeof( Enum ); | |
| } | |
| public override object ConvertFrom( ITypeDescriptorContext context, CultureInfo culture, object value ) | |
| { | |
| foreach ( int i in Enum.GetValues( typeof( PennerDoubleAnimation.Equations ) ) ) | |
| { | |
| if ( Enum.GetName( typeof( PennerDoubleAnimation.Equations ), i ) == value.ToString() ) | |
| return ( PennerDoubleAnimation.Equations ) i; | |
| } | |
| return null; | |
| } | |
| public override object ConvertTo( ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType ) | |
| { | |
| if ( value != null ) | |
| { | |
| return ( ( PennerDoubleAnimation.Equations ) value ).ToString(); | |
| } | |
| return null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment