easings
This commit is contained in:
361
modules/Easing.lua
Normal file
361
modules/Easing.lua
Normal file
@@ -0,0 +1,361 @@
|
||||
--- Easing functions for animations
|
||||
--- Provides 30+ easing functions for smooth animation transitions
|
||||
---
|
||||
--- Easing function type
|
||||
---@alias EasingFunction fun(t: number): number
|
||||
---
|
||||
---@class Easing
|
||||
local Easing = {}
|
||||
|
||||
-- ============================================================================
|
||||
-- Linear
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.linear(t)
|
||||
return t
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Quadratic (Quad)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInQuad(t)
|
||||
return t * t
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutQuad(t)
|
||||
return t * (2 - t)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutQuad(t)
|
||||
return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Cubic
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInCubic(t)
|
||||
return t * t * t
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutCubic(t)
|
||||
local t1 = t - 1
|
||||
return t1 * t1 * t1 + 1
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutCubic(t)
|
||||
return t < 0.5 and 4 * t * t * t or (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Quartic (Quart)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInQuart(t)
|
||||
return t * t * t * t
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutQuart(t)
|
||||
local t1 = t - 1
|
||||
return 1 - t1 * t1 * t1 * t1
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutQuart(t)
|
||||
if t < 0.5 then
|
||||
return 8 * t * t * t * t
|
||||
else
|
||||
local t1 = t - 1
|
||||
return 1 - 8 * t1 * t1 * t1 * t1
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Quintic (Quint)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInQuint(t)
|
||||
return t * t * t * t * t
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutQuint(t)
|
||||
local t1 = t - 1
|
||||
return 1 + t1 * t1 * t1 * t1 * t1
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutQuint(t)
|
||||
if t < 0.5 then
|
||||
return 16 * t * t * t * t * t
|
||||
else
|
||||
local t1 = t - 1
|
||||
return 1 + 16 * t1 * t1 * t1 * t1 * t1
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Exponential (Expo)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInExpo(t)
|
||||
return t == 0 and 0 or math.pow(2, 10 * (t - 1))
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutExpo(t)
|
||||
return t == 1 and 1 or 1 - math.pow(2, -10 * t)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutExpo(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
|
||||
if t < 0.5 then
|
||||
return 0.5 * math.pow(2, 20 * t - 10)
|
||||
else
|
||||
return 1 - 0.5 * math.pow(2, -20 * t + 10)
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Sine
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInSine(t)
|
||||
return 1 - math.cos(t * math.pi / 2)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutSine(t)
|
||||
return math.sin(t * math.pi / 2)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutSine(t)
|
||||
return -(math.cos(math.pi * t) - 1) / 2
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Circular (Circ)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInCirc(t)
|
||||
return 1 - math.sqrt(1 - t * t)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutCirc(t)
|
||||
local t1 = t - 1
|
||||
return math.sqrt(1 - t1 * t1)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutCirc(t)
|
||||
if t < 0.5 then
|
||||
return (1 - math.sqrt(1 - 4 * t * t)) / 2
|
||||
else
|
||||
local t1 = -2 * t + 2
|
||||
return (math.sqrt(1 - t1 * t1) + 1) / 2
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Back (Overshoot)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInBack(t)
|
||||
local c1 = 1.70158
|
||||
local c3 = c1 + 1
|
||||
return c3 * t * t * t - c1 * t * t
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutBack(t)
|
||||
local c1 = 1.70158
|
||||
local c3 = c1 + 1
|
||||
local t1 = t - 1
|
||||
return 1 + c3 * t1 * t1 * t1 + c1 * t1 * t1
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutBack(t)
|
||||
local c1 = 1.70158
|
||||
local c2 = c1 * 1.525
|
||||
|
||||
if t < 0.5 then
|
||||
return (2 * t * 2 * t * ((c2 + 1) * 2 * t - c2)) / 2
|
||||
else
|
||||
local t1 = 2 * t - 2
|
||||
return (t1 * t1 * ((c2 + 1) * t1 + c2) + 2) / 2
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Elastic (Spring)
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
|
||||
local c4 = (2 * math.pi) / 3
|
||||
return -math.pow(2, 10 * t - 10) * math.sin((t * 10 - 10.75) * c4)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
|
||||
local c4 = (2 * math.pi) / 3
|
||||
return math.pow(2, -10 * t) * math.sin((t * 10 - 0.75) * c4) + 1
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
|
||||
local c5 = (2 * math.pi) / 4.5
|
||||
|
||||
if t < 0.5 then
|
||||
return -(math.pow(2, 20 * t - 10) * math.sin((20 * t - 11.125) * c5)) / 2
|
||||
else
|
||||
return (math.pow(2, -20 * t + 10) * math.sin((20 * t - 11.125) * c5)) / 2 + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Bounce
|
||||
-- ============================================================================
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeOutBounce(t)
|
||||
local n1 = 7.5625
|
||||
local d1 = 2.75
|
||||
|
||||
if t < 1 / d1 then
|
||||
return n1 * t * t
|
||||
elseif t < 2 / d1 then
|
||||
local t1 = t - 1.5 / d1
|
||||
return n1 * t1 * t1 + 0.75
|
||||
elseif t < 2.5 / d1 then
|
||||
local t1 = t - 2.25 / d1
|
||||
return n1 * t1 * t1 + 0.9375
|
||||
else
|
||||
local t1 = t - 2.625 / d1
|
||||
return n1 * t1 * t1 + 0.984375
|
||||
end
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInBounce(t)
|
||||
return 1 - Easing.easeOutBounce(1 - t)
|
||||
end
|
||||
|
||||
---@type EasingFunction
|
||||
function Easing.easeInOutBounce(t)
|
||||
if t < 0.5 then
|
||||
return (1 - Easing.easeOutBounce(1 - 2 * t)) / 2
|
||||
else
|
||||
return (1 + Easing.easeOutBounce(2 * t - 1)) / 2
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Configurable Easing Factories
|
||||
-- ============================================================================
|
||||
|
||||
--- Create a custom back easing function with configurable overshoot
|
||||
---@param overshoot number? Overshoot amount (default: 1.70158)
|
||||
---@return EasingFunction
|
||||
function Easing.back(overshoot)
|
||||
overshoot = overshoot or 1.70158
|
||||
local c3 = overshoot + 1
|
||||
|
||||
return function(t)
|
||||
return c3 * t * t * t - overshoot * t * t
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a custom elastic easing function
|
||||
---@param amplitude number? Amplitude (default: 1)
|
||||
---@param period number? Period (default: 0.3)
|
||||
---@return EasingFunction
|
||||
function Easing.elastic(amplitude, period)
|
||||
amplitude = amplitude or 1
|
||||
period = period or 0.3
|
||||
|
||||
return function(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
|
||||
local s = period / 4
|
||||
local a = amplitude
|
||||
|
||||
if a < 1 then
|
||||
a = 1
|
||||
s = period / 4
|
||||
else
|
||||
s = period / (2 * math.pi) * math.asin(1 / a)
|
||||
end
|
||||
|
||||
return a * math.pow(2, -10 * t) * math.sin((t - s) * (2 * math.pi) / period) + 1
|
||||
end
|
||||
end
|
||||
|
||||
--- Get list of all available easing function names
|
||||
---@return string[] names Array of easing function names
|
||||
function Easing.list()
|
||||
return {
|
||||
-- Linear
|
||||
"linear",
|
||||
-- Quad
|
||||
"easeInQuad", "easeOutQuad", "easeInOutQuad",
|
||||
-- Cubic
|
||||
"easeInCubic", "easeOutCubic", "easeInOutCubic",
|
||||
-- Quart
|
||||
"easeInQuart", "easeOutQuart", "easeInOutQuart",
|
||||
-- Quint
|
||||
"easeInQuint", "easeOutQuint", "easeInOutQuint",
|
||||
-- Expo
|
||||
"easeInExpo", "easeOutExpo", "easeInOutExpo",
|
||||
-- Sine
|
||||
"easeInSine", "easeOutSine", "easeInOutSine",
|
||||
-- Circ
|
||||
"easeInCirc", "easeOutCirc", "easeInOutCirc",
|
||||
-- Back
|
||||
"easeInBack", "easeOutBack", "easeInOutBack",
|
||||
-- Elastic
|
||||
"easeInElastic", "easeOutElastic", "easeInOutElastic",
|
||||
-- Bounce
|
||||
"easeInBounce", "easeOutBounce", "easeInOutBounce",
|
||||
}
|
||||
end
|
||||
|
||||
--- Get an easing function by name
|
||||
---@param name string Easing function name
|
||||
---@return EasingFunction? easing The easing function, or nil if not found
|
||||
function Easing.get(name)
|
||||
return Easing[name]
|
||||
end
|
||||
|
||||
return Easing
|
||||
Reference in New Issue
Block a user