var Ease = { linear(t) { return t }, in(t) { return t * t }, out(t) { var d = 1 - t return 1 - d * d }, inout(t) { var d = -2 * t + 2 return t < 0.5 ? 2 * t * t : 1 - (d * d) / 2 }, } function make_easing_fns(num) { var obj = {} obj.in = function (t) { return Math.pow(t, num) } obj.out = function (t) { return 1 - Math.pow(1 - t, num) } var mult = Math.pow(2, num - 1) obj.inout = function (t) { return t < 0.5 ? mult * Math.pow(t, num) : 1 - Math.pow(-2 * t + 2, num) / 2 } return obj } Ease.quad = make_easing_fns(2) Ease.cubic = make_easing_fns(3) Ease.quart = make_easing_fns(4) Ease.quint = make_easing_fns(5) Ease.expo = { in(t) { return t == 0 ? 0 : Math.pow(2, 10 * t - 10) }, out(t) { return t == 1 ? 1 : 1 - Math.pow(2, -10 * t) }, inout(t) { return t == 0 ? 0 : t == 1 ? 1 : t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2 }, } Ease.bounce = { in(t) { return 1 - this.out(1 - t) }, out(t) { var n1 = 7.5625 var d1 = 2.75 if (t < 1 / d1) { return n1 * t * t } else if (t < 2 / d1) { return n1 * (t -= 1.5 / d1) * t + 0.75 } else if (t < 2.5 / d1) { return n1 * (t -= 2.25 / d1) * t + 0.9375 } else return n1 * (t -= 2.625 / d1) * t + 0.984375 }, inout(t) { return t < 0.5 ? (1 - this.out(1 - 2 * t)) / 2 : (1 + this.out(2 * t - 1)) / 2 }, } Ease.sine = { in(t) { return 1 - Math.cos((t * Math.PI) / 2) }, out(t) { return Math.sin((t * Math.PI) / 2) }, inout(t) { return -(Math.cos(Math.PI * t) - 1) / 2 }, } Ease.elastic = { in(t) { return t == 0 ? 0 : t == 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * this.c4) }, out(t) { return t == 0 ? 0 : t == 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * this.c4) + 1 }, inout(t) { return t == 0 ? 0 : t == 1 ? 1 : t < 0.5 ? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * this.c5)) / 2 : (Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * this.c5)) / 2 + 1 }, } Ease.elastic.c4 = (2 * Math.PI) / 3 Ease.elastic.c5 = (2 * Math.PI) / 4.5 Ease.zoom = { // Creates a smooth zoom that maintains constant perceptual speed // ratio is the zoom factor (e.g., 10 for 10x zoom) smooth(ratio) { return function(t) { if (t == 0) return 0 if (t == 1) return 1 if (Math.abs(ratio - 1) < 0.001) return t // Position interpolation formula: (r^t - 1) / (r - 1) return (Math.pow(ratio, t) - 1) / (ratio - 1) } }, // Exponential interpolation for zoom values // Interpolates in logarithmic space for smooth visual zoom exp(startZoom, endZoom) { return function(t) { if (t == 0) return startZoom if (t == 1) return endZoom // Scale := Exp(LinearInterpolate(Ln(Scale1), Ln(Scale2), t)) return Math.exp(Math.log(startZoom) + t * (Math.log(endZoom) - Math.log(startZoom))) } } } return Ease