easing

    Easing functions for smooth animation.

    d3
    ease
    easing
    animation
    transition
    Download zip
    Author
    Version
    0.1.0
    License
    BSD-3-Clause
    Last updated
    last year
    Downloads
    32

    #hackwaly/easing

    A comprehensive MoonBit implementation of easing functions for smooth animations, ported from the popular d3-ease JavaScript library.

    #Overview

    Easing functions are mathematical functions that describe how a value changes over time, commonly used in animations to create natural-looking motion. This package provides a complete collection of easing functions with an API that's both powerful and easy to use.

    All easing functions take a time parameter t between 0.0 and 1.0 and return a transformed value, also typically between 0.0 and 1.0 (though some functions like Back and Elastic can overshoot these bounds for realistic motion effects).

    #Basic Usage

    #Linear Easing

    The simplest easing function - no acceleration or deceleration.

    test "linear easing demo" {
    // Linear easing is the identity function
    inspect(@easing.ease_linear(0.0), content="0")
    inspect(@easing.ease_linear(0.5), content="0.5")
    inspect(@easing.ease_linear(1.0), content="1")
    }

    #Quadratic Easing

    Quadratic easing provides smooth acceleration and deceleration.

    test "quadratic easing demo" {
    // Different curve shapes
    inspect(@easing.ease_quad_in(0.5), content="0.25") // Accelerating
    inspect(@easing.ease_quad_out(0.5), content="0.75") // Decelerating
    inspect(@easing.ease_quad(0.5), content="0.5") // In-out (default)
    }

    #Cubic Easing

    More pronounced curves than quadratic.

    test "cubic easing demo" {
    inspect(@easing.ease_cubic_in(0.5), content="0.125")
    inspect(@easing.ease_cubic_out(0.5), content="0.875")
    inspect(@easing.ease_cubic(0.5), content="0.5")
    }

    #Advanced Easing with Optional Parameters

    #Polynomial Easing

    Configurable polynomial easing with customizable exponent.

    test "polynomial easing with options" {
    // Default exponent is 3.0 (same as cubic)
    let default_poly = @easing.ease_poly_in(0.5)
    inspect(default_poly, content="0.125")

    // Using direct function call with custom exponent
    let quadratic = @easing.poly_in(0.5, exponent=2.0)
    inspect(quadratic, content="0.25")

    let quartic = @easing.poly_in(0.5, exponent=4.0)
    inspect(quartic, content="0.0625")
    }

    #Back Easing with Custom Overshoot

    Creates anticipation by going slightly backwards before moving forward.

    test "back easing with custom overshoot" {
    // Default overshoot
    let normal_back = @easing.ease_back_in(0.5)

    // Custom overshoot for more dramatic effect
    let strong_back = @easing.back_in(0.5, overshoot=3.0)
    let weak_back = @easing.back_in(0.5, overshoot=1.0)

    // Stronger overshoot creates more negative values
    inspect(strong_back < normal_back, content="true")
    inspect(normal_back < weak_back, content="true")
    }

    #Elastic Easing with Custom Parameters

    Creates elastic oscillations like a rubber band or spring.

    test "elastic easing with custom parameters" {
    // Default parameters
    let default_elastic = @easing.ease_elastic_in(0.5)

    // Custom amplitude affects oscillation strength
    let strong_elastic = @easing.elastic_in(0.5, amplitude=2.0)
    inspect(default_elastic != strong_elastic, content="true")

    // Custom period affects oscillation frequency
    let fast_oscillation = @easing.elastic_in(0.5, period=0.1)
    let slow_oscillation = @easing.elastic_in(0.5, period=0.8)
    inspect(fast_oscillation != slow_oscillation, content="true")
    }

    #Specialized Easing Functions

    #Exponential Easing

    Creates dramatic acceleration and deceleration effects.

    test "exponential easing characteristics" {
    // Values change rapidly near the extremes
    let exp_early = @easing.ease_exp_in(0.1)
    let exp_late = @easing.ease_exp_in(0.9)

    // Early values are very small
    inspect(exp_early < 0.01, content="true")
    // Later values grow but slowly at first
    inspect(exp_late < 1.0, content="true")
    }

    #Bounce Easing

    Simulates the motion of a bouncing ball.

    test "bounce easing behavior" {
    // Bounce typically overshoots during animation
    let quarter_bounce = @easing.ease_bounce_out(0.25)
    let half_bounce = @easing.ease_bounce_out(0.5)

    // The bounce creates peaks above the linear progression
    inspect(quarter_bounce > 0.25, content="true")
    inspect(half_bounce > 0.5, content="true")
    }

    #Circle Easing

    Based on quarter-circle curves for smooth transitions.

    test "circle easing smoothness" {
    // Circle easing provides smooth curves
    inspect(@easing.ease_circle_in(0.0), content="0")
    inspect(@easing.ease_circle_out(1.0), content="1")
    inspect(@easing.ease_circle(0.5), content="0.5")
    }

    #Sine Easing

    Natural, smooth curves based on sine functions.

    test "sine easing curves" {
    // Sine creates very natural feeling motion
    let sin_quarter = @easing.ease_sin_in(0.25)
    let sin_half = @easing.ease_sin_out(0.5)

    // Values are between 0 and 1 with smooth transitions
    inspect(sin_quarter > 0.0 && sin_quarter < 0.25, content="true")
    inspect(sin_half > 0.5 && sin_half < 1.0, content="true")
    }

    #API Compatibility

    This library provides both direct function calls and convenience aliases:

    test "API compatibility" {
    // Direct function calls (support optional parameters)
    let poly_custom = @easing.poly_in(0.5, exponent=2.0)
    let back_custom = @easing.back_out(0.5, overshoot=2.0)

    // Convenience aliases (d3-ease compatible names)
    let poly_default = @easing.ease_poly_in(0.5)
    let back_default = @easing.ease_back_out(0.5)

    // Verify the aliases work correctly
    inspect(@easing.ease_linear(0.5) == @easing.linear(0.5), content="true")
    inspect(poly_default, content="0.125") // Default exponent 3.0

    // Demonstrate usage
    ignore(poly_custom)
    ignore(back_custom)
    ignore(back_default)
    }

    #Function Categories

    The library includes these easing function families:

    • Linear: ease_linear - Constant speed
    • Quadratic: ease_quad_* - Gentle curves
    • Cubic: ease_cubic_* - More pronounced curves
    • Polynomial: ease_poly_* - Configurable exponent (supports exponent= parameter)
    • Sine: ease_sin_* - Natural, smooth curves
    • Exponential: ease_exp_* - Dramatic acceleration/deceleration
    • Circle: ease_circle_* - Quarter-circle based curves
    • Back: ease_back_* - Anticipation/overshoot (supports overshoot= parameter)
    • Bounce: ease_bounce_* - Bouncing ball physics
    • Elastic: ease_elastic_* - Spring/rubber band effects (supports amplitude= and period= parameters)

    Each family typically includes *_in, *_out, and *_in_out variants, plus a default variant (usually the *_in_out version).

    #Choosing the Right Easing

    • Linear: Use for simple fades or when you want constant speed
    • Quad/Cubic: Great for general UI transitions - natural but noticeable
    • Sine: Excellent for organic, subtle animations
    • Exponential: Use sparingly for dramatic impact
    • Circle: Good balance of smoothness and visibility
    • Back: Perfect for attention-grabbing effects with anticipation
    • Elastic: Fun and playful - great for casual, game-like interfaces
    • Bounce: Realistic physics simulation for ball-like objects

    Most UI animations benefit from _out or _in_out variants as they provide satisfying deceleration.

    assert_in_delta

    fn assert_in_delta(actual : Double, expected : Double, epsilon? : Double) -> Unit

    Assert that two floating point numbers are approximately equal within epsilon

    back_in

    fn back_in(t : Double, overshoot? : Double) -> Double

    Back ease-in function with configurable overshoot @param t: time parameter (0.0 to 1.0) @param overshoot: the amount of overshoot (default: 1.70158)

    back_in_out

    fn back_in_out(t : Double, overshoot? : Double) -> Double

    Back ease-in-out function with configurable overshoot @param t: time parameter (0.0 to 1.0) @param overshoot: the amount of overshoot (default: 1.70158)

    back_out

    fn back_out(t : Double, overshoot? : Double) -> Double

    Back ease-out function with configurable overshoot @param t: time parameter (0.0 to 1.0) @param overshoot: the amount of overshoot (default: 1.70158)

    bounce_in

    fn bounce_in(t : Double) -> Double

    Bounce ease-in function Inverted bounce effect at the beginning

    bounce_in_out

    fn bounce_in_out(t : Double) -> Double

    Bounce ease-in-out function Bounce effect at both ends

    bounce_out

    fn bounce_out(t : Double) -> Double

    Bounce ease-out function Bounce effect at the end

    circle_in

    fn circle_in(t : Double) -> Double

    Circle ease-in function Acceleration following a circular arc

    circle_in_out

    fn circle_in_out(t : Double) -> Double

    Circle ease-in-out function Acceleration and deceleration following circular arcs

    circle_out

    fn circle_out(t : Double) -> Double

    Circle ease-out function Deceleration following a circular arc

    cubic_in

    fn cubic_in(t : Double) -> Double

    Cubic ease-in function Acceleration from zero velocity, following a cubic curve

    cubic_in_out

    fn cubic_in_out(t : Double) -> Double

    Cubic ease-in-out function Acceleration until halfway, then deceleration

    cubic_out

    fn cubic_out(t : Double) -> Double

    Cubic ease-out function Deceleration to zero velocity, following a cubic curve

    ease_back

    fn ease_back(Double) -> Double

    Back easing functions (using default overshoot)

    ease_back_in

    fn ease_back_in(Double) -> Double

    ease_back_in_out

    fn ease_back_in_out(Double) -> Double

    ease_back_out

    fn ease_back_out(Double) -> Double

    ease_bounce

    fn ease_bounce(Double) -> Double

    Bounce easing functions

    ease_bounce_in

    fn ease_bounce_in(Double) -> Double

    ease_bounce_in_out

    fn ease_bounce_in_out(Double) -> Double

    ease_bounce_out

    fn ease_bounce_out(Double) -> Double

    ease_circle

    fn ease_circle(Double) -> Double

    Circle easing functions

    ease_circle_in

    fn ease_circle_in(Double) -> Double

    ease_circle_in_out

    fn ease_circle_in_out(Double) -> Double

    ease_circle_out

    fn ease_circle_out(Double) -> Double

    ease_cubic

    fn ease_cubic(Double) -> Double

    Cubic easing functions

    ease_cubic_in

    fn ease_cubic_in(Double) -> Double

    ease_cubic_in_out

    fn ease_cubic_in_out(Double) -> Double

    ease_cubic_out

    fn ease_cubic_out(Double) -> Double

    ease_elastic

    fn ease_elastic(Double) -> Double

    Elastic easing functions (using default amplitude and period)

    ease_elastic_in

    fn ease_elastic_in(Double) -> Double

    ease_elastic_in_out

    fn ease_elastic_in_out(Double) -> Double

    ease_elastic_out

    fn ease_elastic_out(Double) -> Double

    ease_exp

    fn ease_exp(Double) -> Double

    Exponential easing functions

    ease_exp_in

    fn ease_exp_in(Double) -> Double

    ease_exp_in_out

    fn ease_exp_in_out(Double) -> Double

    ease_exp_out

    fn ease_exp_out(Double) -> Double

    ease_linear

    fn ease_linear(Double) -> Double

    Linear easing function

    ease_poly

    fn ease_poly(Double) -> Double

    Polynomial easing functions (using default exponent)

    ease_poly_in

    fn ease_poly_in(Double) -> Double

    ease_poly_in_out

    fn ease_poly_in_out(Double) -> Double

    ease_poly_out

    fn ease_poly_out(Double) -> Double

    ease_quad

    fn ease_quad(Double) -> Double

    Quadratic easing functions

    ease_quad_in

    fn ease_quad_in(Double) -> Double

    ease_quad_in_out

    fn ease_quad_in_out(Double) -> Double

    ease_quad_out

    fn ease_quad_out(Double) -> Double

    ease_sin

    fn ease_sin(Double) -> Double

    Sine easing functions

    ease_sin_in

    fn ease_sin_in(Double) -> Double

    ease_sin_in_out

    fn ease_sin_in_out(Double) -> Double

    ease_sin_out

    fn ease_sin_out(Double) -> Double

    elastic_in

    fn elastic_in(t : Double, amplitude? : Double, period? : Double) -> Double

    Elastic ease-in function with configurable amplitude and period @param t: time parameter (0.0 to 1.0) @param amplitude: oscillation amplitude (default: 1.0) @param period: oscillation period (default: 0.3)

    elastic_in_out

    fn elastic_in_out(t : Double, amplitude? : Double, period? : Double) -> Double

    Elastic ease-in-out function with configurable amplitude and period @param t: time parameter (0.0 to 1.0) @param amplitude: oscillation amplitude (default: 1.0) @param period: oscillation period (default: 0.3)

    elastic_out

    fn elastic_out(t : Double, amplitude? : Double, period? : Double) -> Double

    Elastic ease-out function with configurable amplitude and period @param t: time parameter (0.0 to 1.0) @param amplitude: oscillation amplitude (default: 1.0) @param period: oscillation period (default: 0.3)

    exp_in

    fn exp_in(t : Double) -> Double

    Exponential ease-in function Sharp acceleration using exponential curve

    exp_in_out

    fn exp_in_out(t : Double) -> Double

    Exponential ease-in-out function Sharp acceleration and deceleration

    exp_out

    fn exp_out(t : Double) -> Double

    Exponential ease-out function Sharp deceleration using exponential curve

    linear

    fn linear(t : Double) -> Double

    Linear interpolation function Simply returns the input value t as is (identity function) This represents linear motion with no acceleration or deceleration

    poly_in

    fn poly_in(t : Double, exponent? : Double) -> Double

    Polynomial ease-in function with configurable exponent @param t: time parameter (0.0 to 1.0) @param exponent: the exponent for the polynomial (default: 3.0)

    poly_in_out

    fn poly_in_out(t : Double, exponent? : Double) -> Double

    Polynomial ease-in-out function with configurable exponent @param t: time parameter (0.0 to 1.0) @param exponent: the exponent for the polynomial (default: 3.0)

    poly_out

    fn poly_out(t : Double, exponent? : Double) -> Double

    Polynomial ease-out function with configurable exponent @param t: time parameter (0.0 to 1.0) @param exponent: the exponent for the polynomial (default: 3.0)

    quad_in

    fn quad_in(t : Double) -> Double

    Quadratic ease-in function Acceleration from zero velocity, following a quadratic curve

    quad_in_out

    fn quad_in_out(t : Double) -> Double

    Quadratic ease-in-out function Acceleration until halfway, then deceleration

    quad_out

    fn quad_out(t : Double) -> Double

    Quadratic ease-out function Deceleration to zero velocity, following a quadratic curve

    sin_in

    fn sin_in(t : Double) -> Double

    Sine ease-in function Smooth acceleration using cosine

    sin_in_out

    fn sin_in_out(t : Double) -> Double

    Sine ease-in-out function Smooth acceleration and deceleration

    sin_out

    fn sin_out(t : Double) -> Double

    Sine ease-out function Smooth deceleration using sine

    test_range

    fn test_range(_name : String, func : (Double) -> Double, test_values : Array[(Double, Double)]) -> Unit

    Test that a function returns values within expected bounds

    tpmt

    fn tpmt(x : Double) -> Double

    tpmt is two power minus ten times t scaled to [0,1] This function computes (2^(-10 * x) - 0.0009765625) * 1.0009775171065494

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io