-
Notifications
You must be signed in to change notification settings - Fork 0
/
JSTween.js
111 lines (110 loc) · 3.81 KB
/
JSTween.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* @callback onUpdate - What to run every time the tween updates.
* @param {number} frame
* @param {number} second
* @param {number} percent
* @param {number} easePercent
* @param {number} value - The value, without prefix/suffix formatting.
* @param {string} formattedValue - The value, with prefix/suffix formatting.
*/
/**
* @callback onFinish - What to run when the tween ends.
* @param {Object} time - The properties that defined how to animate this object.
* @param {Object} config - The properties that defined how to style this animation.
* @param {number} [loops] - How many times the tween has looped.
*/
export function JSTween() {
const tweentypes = {
NORMAL: 0,
FOREVER: 2,
CONTINUE: 4,
PINGPONG: 8,
__NOOP: (x) => {return x;}
};
function lerp(a, b, t) {
return (1 - t) * a + t * b;
}
/**
* @function tween
* Creates a tween to animate properties of an object.
* @param {string} object - The object with the properties being animated.
* @param {string[]} prop - The properties that will be animated.
* @param {Object} time - The properties that define how to animate the object.
* @param {number} time.from - The initial value to animate from.
* @param {number} time.to - The new value to animate to.
* @param {number} time.time - The time it takes to animate the object.
* @param {number} [time.type] - Defines how the animation works.
* @param {Object} [config] - The properties that define how to style the animation.
* @param {Function} [config.ease] - The ease and smoothness of the animation.
* @param {Function} [config.onStart] - What to run when the tween starts.
* @param {onUpdate} [config.onUpdate] - What to run every time the tween updates.
* @param {onFinish} [config.onFinish] - What to run when the tween ends.
* @param {string} [config.prefix] - What string to put before the value.
* @param {string} [config.suffix] - What string to put after the value.
* @returns {Function} - End the tween manually.
*/
const tween = (object, prop, time, config) => {
time.type = time.type ?? 0;
var config = config ?? {};
config.ease = config.ease ?? tweentypes.__NOOP;
config.onStart = config.onStart ?? tweentypes.__NOOP;
config.onUpdate = config.onUpdate ?? tweentypes.__NOOP;
config.onFinish = config.onFinish ?? tweentypes.__NOOP;
config.prefix = config.prefix ?? "";
config.suffix = config.suffix ?? "";
var frame = 0;
var startTime = performance.now() / 1000;
var loops = 0;
var loopIsDone = true;
config.onStart();
var updateFunc = () => {
var curTime = (performance.now() / 1000) - startTime;
var curPercent = curTime / time.time;
for (let i in prop) {
object[prop[i]] = config.prefix + lerp(time.from, time.to, config.ease(curPercent)) + config.suffix;
}
if (curPercent >= 1) {
switch (time.type) {
case 0:
for (let i in prop) {
object[prop[i]] = config.prefix + time.to + config.suffix;
}
loopIsDone = false;
break;
case 2:
startTime = performance.now() / 1000;
break;
case 4:
break;
case 8:
var x = time.from;
time.from = time.to;
time.to = x;
startTime = performance.now() / 1000;
break;
}
loops++;
config.onFinish(time, config, loops);
}
config.onUpdate(frame, curTime, curPercent, config.ease(curPercent), lerp(time.from, time.to, config.ease(curPercent)), config.prefix + lerp(time.from, time.to, config.ease(curPercent)) + config.suffix);
frame++;
if (loopIsDone) {
window.requestAnimationFrame(updateFunc);
}
};
window.requestAnimationFrame(updateFunc);
return (clean) => {
if (!clean) {
for (let i in prop) {
object[prop[i]] = config.prefix + time.to + config.suffix;
}
}
time.type = 0;
loopIsDone = false;
}
};
return {
tweentypes: tweentypes,
tween: tween
};
}