easing

Easing functions for smooth animation.

d3
ease
easing
animation
transition
Download zip
Author
Version
0.1.0
License
BSD-3-Clause
Last updated
12 months ago
Downloads
18

#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