-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathspring.js
More file actions
83 lines (73 loc) · 2.14 KB
/
spring.js
File metadata and controls
83 lines (73 loc) · 2.14 KB
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
// Based on https://github.com/hatsumatsu/spring
export const makeSpring = (
initialValue = 0,
{
stiffness: initialStiffness = 200,
damping: initialDamping = 10,
precision: initialPrecision = 50,
mass: initialMass = 1,
}
) => {
let stiffness = initialStiffness;
let damping = initialDamping;
let precision = initialPrecision;
let mass = initialMass;
let currentValue = initialValue;
let endValue = initialValue; // initialize spring at rest
let velocity = 0;
let atRest = true;
let pendingResolver = null;
const update = (deltaTime) => {
const difference = endValue - currentValue;
const acceleration = (stiffness * difference) / mass - damping * velocity;
const newVelocity = velocity + acceleration * (deltaTime / 1000);
const newValue = currentValue + newVelocity * (deltaTime / 1000);
atRest =
Math.abs(newVelocity) < 1 / precision &&
Math.abs(endValue - newValue) < 1 / precision;
currentValue = atRest ? endValue : newValue;
velocity = atRest ? 0 : newVelocity;
// If the spring is at rest and we have a pending resolver, resolve it
if (atRest && pendingResolver) {
pendingResolver();
pendingResolver = null;
}
};
const updateProps = ({
stiffness: passedStiffness = stiffness,
damping: passedDamping = damping,
precision: passedPrecision = precision,
mass: passedMass = mass,
}) => {
stiffness = passedStiffness;
damping = passedDamping;
precision = passedPrecision;
mass = passedMass;
};
const setEndValue = (v) => {
endValue = v;
// If already at rest and at the target value, resolve immediately
return new Promise((resolve) => {
atRest && currentValue === endValue
? resolve()
: (pendingResolver = resolve);
});
};
const resetValue = (v = initialValue) => {
currentValue = v;
endValue = v;
velocity = 0;
atRest = true;
pendingResolver = null;
};
return {
setEndValue,
resetValue,
getCurrentValue: () => currentValue,
update,
updateProps,
getStiffness: () => stiffness,
getDamping: () => damping,
getMass: () => mass,
};
};