| File: Animations\Easing.cs | Web Access |
| Project: src\src\Core\src\Core.csproj (Microsoft.Maui) |
using System; using System.ComponentModel; using Microsoft.Maui.Converters; namespace Microsoft.Maui { /// <summary> /// Functions that modify values non-linearly, generally used for animations. /// </summary> /// <remarks> /// Easing functions are applied to input values in the range [0,1]. The cubic easing functions are often considered to look most natural. /// If developers wish to use their own easing functions, they should return a value of 0 for an input of 0 and a value of 1 for an input of 1 or the animation will have a jump. /// </remarks> [TypeConverter(typeof(EasingTypeConverter))] public class Easing { /// <summary> /// The default easing function that is used. /// Defaults to <see cref="CubicInOut"/>. /// </summary> public static Easing Default => CubicInOut; /// <summary> /// Linear transformation. /// </summary> public static readonly Easing Linear = new(x => x); /// <summary> /// Smoothly decelerates. /// </summary> public static readonly Easing SinOut = new(x => Math.Sin(x * Math.PI * 0.5f)); /// <summary> /// Smoothly accelerates. /// </summary> public static readonly Easing SinIn = new(x => 1.0f - Math.Cos(x * Math.PI * 0.5f)); /// <summary> /// Accelerates in and decelerates out. /// </summary> public static readonly Easing SinInOut = new(x => -Math.Cos(Math.PI * x) / 2.0f + 0.5f); /// <summary> /// Starts slowly and accelerates. /// </summary> public static readonly Easing CubicIn = new(x => x * x * x); /// <summary> /// Starts quickly and the decelerates. /// </summary> public static readonly Easing CubicOut = new(x => Math.Pow(x - 1.0f, 3.0f) + 1.0f); /// <summary> /// Accelerates and decelerates. Often a natural-looking choice. /// </summary> public static readonly Easing CubicInOut = new(x => x < 0.5f ? Math.Pow(x * 2.0f, 3.0f) / 2.0f : (Math.Pow((x - 1) * 2.0f, 3.0f) + 2.0f) / 2.0f); /// <summary> /// Leaps to final values, bounces 3 times, and settles. /// </summary> public static readonly Easing BounceOut; /// <summary> /// Jumps towards, and then bounces as it settles at the final value. /// </summary> public static readonly Easing BounceIn; /// <summary> /// Moves away and then leaps toward the final value. /// </summary> public static readonly Easing SpringIn = new(x => x * x * ((1.70158f + 1) * x - 1.70158f)); /// <summary> /// Overshoots and then returns. /// </summary> public static readonly Easing SpringOut = new(x => (x - 1) * (x - 1) * ((1.70158f + 1) * (x - 1) + 1.70158f) + 1); readonly Func<double, double> _easingFunc; static Easing() { BounceOut = new Easing(p => { if (p < 1 / 2.75f) { return 7.5625f * p * p; } if (p < 2 / 2.75f) { p -= 1.5f / 2.75f; return 7.5625f * p * p + .75f; } if (p < 2.5f / 2.75f) { p -= 2.25f / 2.75f; return 7.5625f * p * p + .9375f; } p -= 2.625f / 2.75f; return 7.5625f * p * p + .984375f; }); BounceIn = new Easing(p => 1.0f - BounceOut.Ease(1 - p)); } /// <summary> /// Creates a new <see cref="Easing" /> object with the <paramref name="easingFunc" /> function. /// </summary> /// <param name="easingFunc">A function that maps animation times.</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="easingFunc"/> is <see langword="null"/>.</exception> public Easing(Func<double, double> easingFunc) { _easingFunc = easingFunc ?? throw new ArgumentNullException(nameof(easingFunc)); } /// <summary> /// Applies the easing function to the specified value <paramref name="v" />. /// </summary> /// <param name="v">A value in the range [0,1] to which the easing function should be applied.</param> /// <returns>The value of the easing function when applied to the value <paramref name="v" />.</returns> public double Ease(double v) { return _easingFunc(v); } /// <summary> /// Converts a function into an <see cref="T:Microsoft.Maui.Easing" />. /// </summary> /// <param name="func">An easing function.</param> /// <remarks>An easing function should return a value of (or near) 0 at 0 and 1 (or near) for 1.</remarks> public static implicit operator Easing(Func<double, double> func) { return new Easing(func); } } }