Search code examples
c#wpfeasing

WPF : Easing Function with Cubic Bezier Curve like in CSS


My goal is to reproduce this mouse over animation in WPF :
https://xaalek.w3spaces.com/saved-from-Tryit-2022-03-21-n3xl2.html?bypass-cache=74310593

Currently I have something like this in my code :

var doubleAnimation = new DoubleAnimation(1, new Duration(TimeSpan.FromMilliseconds(280)))
{
    FillBehavior = FillBehavior.HoldEnd,
    EasingFunction = new CubicEase()
};

But the result is not perfect.
Is it possible to create a custom easing with a Cubic Bezier Curve like in CSS ?

transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1)

I saw that we can create custom Easing Function by inheriting EasingFunctionBase

I need to specify the coordinates of points on the curve to get the same result.
https://cubic-bezier.com/#.4,0,.2,1

I could create a Custom Easing Function like this :

internal class MaterialEasingFunction : EasingFunctionBase
    {
        public MaterialEasingFunction()
            : base()
        {
            EasingMode = EasingMode.EaseInOut;
        }

        protected override double EaseInCore(double normalizedTime) => Math.Pow(normalizedTime, 3);

        protected override Freezable CreateInstanceCore() => new MaterialEasingFunction();

    }

But I don't know how I can specify the coordinates of the points on the curve.

Do you have any idea how I could do this?


Solution

  • We can use AccelerationRatio and DecelerationRatio properties on a DoubleAnimation : https://learn.microsoft.com/fr-fr/dotnet/desktop/wpf/graphics-multimedia/how-to-accelerate-or-decelerate-an-animation?view=netframeworkdesktop-4.8

    This is the CSS syntax for cubic bezier :

    cubic-bezier(x1,y1,x2,y2)
    

    In this case, we just using x1 and x2.
    Since the coordinates go from 0 to 1, we can use the x-coordinates of the points as acceleration and deceleration ratios

    This is the final result :

    var doubleAnimation = new DoubleAnimation()
    {
        To = 1,
        Duration = new Duration(TimeSpan.FromMilliseconds(280)),
        FillBehavior = FillBehavior.HoldEnd,
        EasingFunction = new CubicEase(),
        AccelerationRatio = 0.4,
        DecelerationRatio = 0.2
    };