UNPKG

9.71 kBJavaScriptView Raw
1import { __read } from "tslib";
2/**
3 * ported from https://github.com/okikio/native/blob/master/packages/animate/src/custom-easing.ts
4 */
5
6import { bezier } from './bezier-easing';
7export var convertToDash = function convertToDash(str) {
8 str = str.replace(/([A-Z])/g, function (letter) {
9 return "-".concat(letter.toLowerCase());
10 }); // Remove first dash
11
12 return str.charAt(0) === '-' ? str.substr(1) : str;
13};
14export var limit = function limit(value, min, max) {
15 return Math.min(Math.max(value, min), max);
16};
17/**
18 Easing Functions from anime.js, they are tried and true, so, its better to use them instead of other alternatives
19*/
20
21export var Quad = function Quad(t) {
22 return Math.pow(t, 2);
23};
24export var Cubic = function Cubic(t) {
25 return Math.pow(t, 3);
26};
27export var Quart = function Quart(t) {
28 return Math.pow(t, 4);
29};
30export var Quint = function Quint(t) {
31 return Math.pow(t, 5);
32};
33export var Expo = function Expo(t) {
34 return Math.pow(t, 6);
35};
36export var Sine = function Sine(t) {
37 return 1 - Math.cos(t * Math.PI / 2);
38};
39export var Circ = function Circ(t) {
40 return 1 - Math.sqrt(1 - t * t);
41};
42export var Back = function Back(t) {
43 return t * t * (3 * t - 2);
44};
45export var Bounce = function Bounce(t) {
46 var pow2,
47 b = 4;
48
49 while (t < ((pow2 = Math.pow(2, --b)) - 1) / 11) {}
50
51 return 1 / Math.pow(4, 3 - b) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - t, 2);
52};
53export var Elastic = function Elastic(t, params) {
54 if (params === void 0) {
55 params = [];
56 }
57
58 var _a = __read(params, 2),
59 _b = _a[0],
60 amplitude = _b === void 0 ? 1 : _b,
61 _c = _a[1],
62 period = _c === void 0 ? 0.5 : _c;
63
64 var a = limit(Number(amplitude), 1, 10);
65 var p = limit(Number(period), 0.1, 2);
66 if (t === 0 || t === 1) return t;
67 return -a * Math.pow(2, 10 * (t - 1)) * Math.sin((t - 1 - p / (Math.PI * 2) * Math.asin(1 / a)) * (Math.PI * 2) / p);
68};
69export var Spring = function Spring(t, params, duration) {
70 if (params === void 0) {
71 params = [];
72 }
73
74 var _a = __read(params, 4),
75 _b = _a[0],
76 mass = _b === void 0 ? 1 : _b,
77 _c = _a[1],
78 stiffness = _c === void 0 ? 100 : _c,
79 _d = _a[2],
80 damping = _d === void 0 ? 10 : _d,
81 _e = _a[3],
82 velocity = _e === void 0 ? 0 : _e;
83
84 mass = limit(mass, 0.1, 1000);
85 stiffness = limit(stiffness, 0.1, 1000);
86 damping = limit(damping, 0.1, 1000);
87 velocity = limit(velocity, 0.1, 1000);
88 var w0 = Math.sqrt(stiffness / mass);
89 var zeta = damping / (2 * Math.sqrt(stiffness * mass));
90 var wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0;
91 var a = 1;
92 var b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0;
93 var progress = duration ? duration * t / 1000 : t;
94
95 if (zeta < 1) {
96 progress = Math.exp(-progress * zeta * w0) * (a * Math.cos(wd * progress) + b * Math.sin(wd * progress));
97 } else {
98 progress = (a + b * progress) * Math.exp(-progress * w0);
99 }
100
101 if (t === 0 || t === 1) return t;
102 return 1 - progress;
103};
104/**
105 * Cache the durations at set easing parameters
106 */
107
108export var EasingDurationCache = new Map();
109/**
110 * The threshold for an infinite loop
111 */
112
113export var INTINITE_LOOP_LIMIT = 10000;
114/** Convert easing parameters to Array of numbers, e.g. "spring(2, 500)" to [2, 500] */
115
116export var parseEasingParameters = function parseEasingParameters(str) {
117 var match = /(\(|\s)([^)]+)\)?/.exec(str);
118 return match ? match[2].split(',').map(function (value) {
119 var num = parseFloat(value);
120 return !Number.isNaN(num) ? num : value.trim();
121 }) : [];
122};
123/**
124 * The spring easing function will only look smooth at certain durations, with certain parameters.
125 * This functions returns the optimal duration to create a smooth springy animation based on physics
126 *
127 * Note: it can also be used to determine the optimal duration of other types of easing function, but be careful of 'in-'
128 * easing functions, because of the nature of the function it can sometimes create an infinite loop, I suggest only using
129 * `getEasingDuration` for `spring`, specifically 'out-spring' and 'spring'
130 */
131// export const getEasingDuration = (easing: string | TypeEasingFunction = 'spring') => {
132// if (EasingDurationCache.has(easing)) return EasingDurationCache.get(easing);
133// // eslint-disable-next-line @typescript-eslint/no-use-before-define
134// const easingFunction = typeof easing == 'function' ? easing : getEasingFunction(easing as string);
135// const params = typeof easing == 'function' ? [] : parseEasingParameters(easing);
136// const frame = 1 / 6;
137// let elapsed = 0;
138// let rest = 0;
139// let count = 0;
140// while (++count < INTINITE_LOOP_LIMIT) {
141// elapsed += frame;
142// if (easingFunction(elapsed, params, undefined) === 1) {
143// rest++;
144// if (rest >= 16) break;
145// } else {
146// rest = 0;
147// }
148// }
149// const duration = elapsed * frame * 1000;
150// EasingDurationCache.set(easing, duration);
151// return duration;
152// };
153
154/**
155 These Easing Functions are based off of the Sozi Project's easing functions
156 https://github.com/sozi-projects/Sozi/blob/d72e44ebd580dc7579d1e177406ad41e632f961d/src/js/player/Timing.js
157*/
158
159export var Steps = function Steps(t, params) {
160 if (params === void 0) {
161 params = [];
162 }
163
164 var _a = __read(params, 2),
165 _b = _a[0],
166 steps = _b === void 0 ? 10 : _b,
167 type = _a[1];
168
169 var trunc = type == 'start' ? Math.ceil : Math.floor;
170 return trunc(limit(t, 0, 1) * steps) / steps;
171}; // @ts-ignore
172
173export var Bezier = function Bezier(t, params) {
174 if (params === void 0) {
175 params = [];
176 }
177
178 var _a = __read(params, 4),
179 mX1 = _a[0],
180 mY1 = _a[1],
181 mX2 = _a[2],
182 mY2 = _a[3];
183
184 return bezier(mX1, mY1, mX2, mY2)(t);
185};
186/** The default `ease-in` easing function */
187
188export var easein = bezier(0.42, 0.0, 1.0, 1.0);
189/** Converts easing functions to their `out`counter parts */
190
191export var EaseOut = function EaseOut(ease) {
192 return function (t, params, duration) {
193 if (params === void 0) {
194 params = [];
195 }
196
197 return 1 - ease(1 - t, params, duration);
198 };
199};
200/** Converts easing functions to their `in-out` counter parts */
201
202export var EaseInOut = function EaseInOut(ease) {
203 return function (t, params, duration) {
204 if (params === void 0) {
205 params = [];
206 }
207
208 return t < 0.5 ? ease(t * 2, params, duration) / 2 : 1 - ease(t * -2 + 2, params, duration) / 2;
209 };
210};
211/** Converts easing functions to their `out-in` counter parts */
212
213export var EaseOutIn = function EaseOutIn(ease) {
214 return function (t, params, duration) {
215 if (params === void 0) {
216 params = [];
217 }
218
219 return t < 0.5 ? (1 - ease(1 - t * 2, params, duration)) / 2 : (ease(t * 2 - 1, params, duration) + 1) / 2;
220 };
221};
222/**
223 * The default list of easing functions, do note this is different from {@link EASING}
224 */
225
226export var EasingFunctions = {
227 steps: Steps,
228 'step-start': function stepStart(t) {
229 return Steps(t, [1, 'start']);
230 },
231 'step-end': function stepEnd(t) {
232 return Steps(t, [1, 'end']);
233 },
234 linear: function linear(t) {
235 return t;
236 },
237 'cubic-bezier': Bezier,
238 ease: function ease(t) {
239 return Bezier(t, [0.25, 0.1, 0.25, 1.0]);
240 },
241 in: easein,
242 out: EaseOut(easein),
243 'in-out': EaseInOut(easein),
244 'out-in': EaseOutIn(easein),
245 'in-quad': Quad,
246 'out-quad': EaseOut(Quad),
247 'in-out-quad': EaseInOut(Quad),
248 'out-in-quad': EaseOutIn(Quad),
249 'in-cubic': Cubic,
250 'out-cubic': EaseOut(Cubic),
251 'in-out-cubic': EaseInOut(Cubic),
252 'out-in-cubic': EaseOutIn(Cubic),
253 'in-quart': Quart,
254 'out-quart': EaseOut(Quart),
255 'in-out-quart': EaseInOut(Quart),
256 'out-in-quart': EaseOutIn(Quart),
257 'in-quint': Quint,
258 'out-quint': EaseOut(Quint),
259 'in-out-quint': EaseInOut(Quint),
260 'out-in-quint': EaseOutIn(Quint),
261 'in-expo': Expo,
262 'out-expo': EaseOut(Expo),
263 'in-out-expo': EaseInOut(Expo),
264 'out-in-expo': EaseOutIn(Expo),
265 'in-sine': Sine,
266 'out-sine': EaseOut(Sine),
267 'in-out-sine': EaseInOut(Sine),
268 'out-in-sine': EaseOutIn(Sine),
269 'in-circ': Circ,
270 'out-circ': EaseOut(Circ),
271 'in-out-circ': EaseInOut(Circ),
272 'out-in-circ': EaseOutIn(Circ),
273 'in-back': Back,
274 'out-back': EaseOut(Back),
275 'in-out-back': EaseInOut(Back),
276 'out-in-back': EaseOutIn(Back),
277 'in-bounce': Bounce,
278 'out-bounce': EaseOut(Bounce),
279 'in-out-bounce': EaseInOut(Bounce),
280 'out-in-bounce': EaseOutIn(Bounce),
281 'in-elastic': Elastic,
282 'out-elastic': EaseOut(Elastic),
283 'in-out-elastic': EaseInOut(Elastic),
284 'out-in-elastic': EaseOutIn(Elastic),
285 spring: Spring,
286 'spring-in': Spring,
287 'spring-out': EaseOut(Spring),
288 'spring-in-out': EaseInOut(Spring),
289 'spring-out-in': EaseOutIn(Spring)
290};
291/**
292 * Convert string easing to their proper form
293 */
294
295export var complexEasingSyntax = function complexEasingSyntax(ease) {
296 return convertToDash(ease).replace(/^ease-/, '') // Remove the "ease-" keyword
297 .replace(/(\(|\s).+/, '') // Remove the function brackets and parameters
298 .toLowerCase().trim();
299};
300/** Re-maps a number from one range to another. Numbers outside the range are not clamped to 0 and 1, because out-of-range values are often intentional and useful. */
301
302export var getEasingFunction = function getEasingFunction(ease) {
303 return EasingFunctions[complexEasingSyntax(ease)] || EasingFunctions.linear;
304}; // /**
305// * Allows you to register new easing functions
306// */
307// export const registerEasingFunction = (key: string, fn: TypeEasingFunction) => {
308// Object.assign(EasingFunctions, {
309// [key]: fn,
310// });
311// };
312// /**
313// * Allows you to register multiple new easing functions
314// */
315// export const registerEasingFunctions = (...obj: typeof EasingFunctions[]) => {
316// Object.assign(EasingFunctions, ...obj);
317// };
\No newline at end of file