physics-animator 0.2.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/cjs/Animator.js +255 -157
- package/dist/cjs/IFieldAnimator.js +8 -0
- package/dist/cjs/{Spring.js → animators/SpringAnimator.js} +57 -12
- package/dist/cjs/animators/TweenAnimator.js +75 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/react/useSpringValue.js +12 -42
- package/dist/esm/Animator.js +254 -156
- package/dist/esm/IFieldAnimator.js +5 -0
- package/dist/esm/{Spring.js → animators/SpringAnimator.js} +56 -11
- package/dist/esm/animators/TweenAnimator.js +68 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/react/useSpringValue.js +12 -42
- package/dist/types/Animator.d.ts +88 -63
- package/dist/types/IFieldAnimator.d.ts +9 -0
- package/dist/types/{Spring.d.ts → animators/SpringAnimator.d.ts} +11 -1
- package/dist/types/animators/TweenAnimator.d.ts +21 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/react/useSpringState.d.ts +1 -1
- package/dist/types/react/useSpringValue.d.ts +1 -1
- package/package.json +2 -10
- package/dist/cjs/three/ThreeAnimator.js +0 -453
- package/dist/cjs/three/index.js +0 -17
- package/dist/esm/three/ThreeAnimator.js +0 -450
- package/dist/esm/three/index.js +0 -1
- package/dist/types/three/ThreeAnimator.d.ts +0 -56
- package/dist/types/three/index.d.ts +0 -1
|
@@ -1,8 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { StepResult } from "../IFieldAnimator.js";
|
|
2
|
+
const defaultSpringParameters = {
|
|
3
|
+
duration_s: 0.5,
|
|
4
|
+
};
|
|
5
|
+
export const SpringAnimator = {
|
|
6
|
+
createState(obj, field, target, params) {
|
|
7
|
+
return {
|
|
8
|
+
x: obj[field],
|
|
9
|
+
targetX: target,
|
|
10
|
+
v: 0,
|
|
11
|
+
physicsParameters: Spring.getPhysicsParameters(params ?? defaultSpringParameters),
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
updateState(state, object, field, target, params) {
|
|
15
|
+
state.x = object[field];
|
|
16
|
+
state.targetX = target;
|
|
17
|
+
state.physicsParameters = Spring.getPhysicsParameters(params ?? defaultSpringParameters);
|
|
18
|
+
},
|
|
19
|
+
step(state, object, field, params, dt_s) {
|
|
20
|
+
let physicsParameters = state.physicsParameters;
|
|
21
|
+
// step the spring
|
|
22
|
+
if (physicsParameters != null && isFinite(physicsParameters.strength) && isFinite(physicsParameters.damping)) {
|
|
23
|
+
Spring.stepSpring(dt_s, state, physicsParameters);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// instant transition: set to the target
|
|
27
|
+
state.x = state.targetX;
|
|
28
|
+
state.v = 0;
|
|
29
|
+
}
|
|
30
|
+
// update the object
|
|
31
|
+
object[field] = state.x;
|
|
32
|
+
// complete the animation if it's close enough to the target and velocity is close to 0
|
|
33
|
+
if (Math.abs(state.x - state.targetX) < 0.0001 && Math.abs(state.v) < 0.0001) {
|
|
34
|
+
object[field] = state.targetX;
|
|
35
|
+
return StepResult.Complete;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return StepResult.Continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
6
42
|
export var Spring;
|
|
7
43
|
(function (Spring) {
|
|
8
44
|
/**
|
|
@@ -13,7 +49,7 @@ export var Spring;
|
|
|
13
49
|
* `strength = damping * damping / 4`
|
|
14
50
|
*/
|
|
15
51
|
function Exponential(options) {
|
|
16
|
-
//
|
|
52
|
+
// found numerically
|
|
17
53
|
const halfLifeConstant = 3.356694; // from solve (1+u)*exp(-u)=0.5 for u, and constant = 2u
|
|
18
54
|
const pointOnePercentConstant = 18.46682; // from solve (1+u)*exp(-u)=0.001 for u, and constant = 2u
|
|
19
55
|
const damping = pointOnePercentConstant / options.duration_s;
|
|
@@ -26,11 +62,12 @@ export var Spring;
|
|
|
26
62
|
// -2ln(0.001) = b t
|
|
27
63
|
const durationTarget = 0.001; // 0.1% of target
|
|
28
64
|
let damping = -2 * Math.log(durationTarget) / duration_s;
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
65
|
+
// see https://www.desmos.com/calculator/h43ylohte7
|
|
66
|
+
const strength = 0.25 * (((2 * bounce * Math.PI) / duration_s) ** 2 + damping ** 2);
|
|
67
|
+
return {
|
|
68
|
+
damping,
|
|
69
|
+
strength,
|
|
70
|
+
};
|
|
34
71
|
}
|
|
35
72
|
Spring.Underdamped = Underdamped;
|
|
36
73
|
function getPhysicsParameters(parameters) {
|
|
@@ -53,6 +90,8 @@ export var Spring;
|
|
|
53
90
|
* @param dt_s
|
|
54
91
|
* @param state
|
|
55
92
|
* @param parameters
|
|
93
|
+
*
|
|
94
|
+
* If parameters are NaN or infinite, the spring will skip to the target
|
|
56
95
|
*/
|
|
57
96
|
function stepSpring(dt_s, state, parameters) {
|
|
58
97
|
// analytic integration (unconditionally stable)
|
|
@@ -71,6 +110,12 @@ export var Spring;
|
|
|
71
110
|
return;
|
|
72
111
|
if (dt_s === 0)
|
|
73
112
|
return;
|
|
113
|
+
if (!isFinite(k) || !isFinite(b) || !isFinite(v0) || !isFinite(dx0)) {
|
|
114
|
+
// skip to target
|
|
115
|
+
state.x = state.targetX;
|
|
116
|
+
state.v = 0;
|
|
117
|
+
return 0; // no energy
|
|
118
|
+
}
|
|
74
119
|
let critical = k * 4 - b * b;
|
|
75
120
|
if (critical > 0) {
|
|
76
121
|
// under damped
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { StepResult } from "../IFieldAnimator.js";
|
|
2
|
+
const defaultParams = {
|
|
3
|
+
duration_s: 0.5, // default duration of the tween in seconds
|
|
4
|
+
easingFn: linearStep, // default easing function is linear
|
|
5
|
+
};
|
|
6
|
+
export const TweenAnimator = {
|
|
7
|
+
createState(obj, field, target, params) {
|
|
8
|
+
return {
|
|
9
|
+
x0: obj[field], // initial value of the field
|
|
10
|
+
t0_ms: performance.now(), // time when the tween started in milliseconds
|
|
11
|
+
target: target,
|
|
12
|
+
velocity: 0,
|
|
13
|
+
...(params ?? defaultParams),
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
updateState(state, object, field, target, params) {
|
|
17
|
+
state.target = target;
|
|
18
|
+
state.x0 = object[field]; // update the initial value of the field
|
|
19
|
+
state.t0_ms = performance.now(); // reset the start time of the tween
|
|
20
|
+
state.duration_s = params?.duration_s ?? defaultParams.duration_s; // update the duration of the tween
|
|
21
|
+
state.easingFn = params?.easingFn ?? defaultParams.easingFn; //
|
|
22
|
+
},
|
|
23
|
+
step(state, object, field, params, dt_s) {
|
|
24
|
+
// step the tween
|
|
25
|
+
let x = object[field];
|
|
26
|
+
params.easingFn(object, field, state.target, state, dt_s);
|
|
27
|
+
let x_new = object[field];
|
|
28
|
+
state.velocity = (x_new - x) / dt_s;
|
|
29
|
+
// remove the tween if it's complete
|
|
30
|
+
let deltaTime_s = (performance.now() - state.t0_ms) / 1000;
|
|
31
|
+
if (deltaTime_s >= state.duration_s) {
|
|
32
|
+
object[field] = state.target;
|
|
33
|
+
return StepResult.Complete;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return StepResult.Continue;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export function linearStep(object, field, target, params, dt_s) {
|
|
41
|
+
let dx = target - params.x0;
|
|
42
|
+
let t = (performance.now() - params.t0_ms) / 1000;
|
|
43
|
+
let u = t / params.duration_s;
|
|
44
|
+
let x_new = params.x0 + dx * u;
|
|
45
|
+
object[field] = x_new;
|
|
46
|
+
}
|
|
47
|
+
// cubic ease in out
|
|
48
|
+
export function easeInOutStep(object, field, target, params, dt_s) {
|
|
49
|
+
let dx = target - params.x0;
|
|
50
|
+
let t = (performance.now() - params.t0_ms) / 1000;
|
|
51
|
+
let u = t / params.duration_s;
|
|
52
|
+
let x_new = params.x0 + dx * u * u * (3 - 2 * u);
|
|
53
|
+
object[field] = x_new;
|
|
54
|
+
}
|
|
55
|
+
export function easeInStep(object, field, target, params, dt_s) {
|
|
56
|
+
let dx = target - params.x0;
|
|
57
|
+
let t = (performance.now() - params.t0_ms) / 1000;
|
|
58
|
+
let u = t / params.duration_s;
|
|
59
|
+
let x_new = params.x0 + dx * u * u * u;
|
|
60
|
+
object[field] = x_new;
|
|
61
|
+
}
|
|
62
|
+
export function easeOutStep(object, field, target, params, dt_s) {
|
|
63
|
+
let dx = target - params.x0;
|
|
64
|
+
let t = (performance.now() - params.t0_ms) / 1000;
|
|
65
|
+
let u = t / params.duration_s;
|
|
66
|
+
let x_new = params.x0 + dx * (1 - Math.pow(1 - u, 3));
|
|
67
|
+
object[field] = x_new;
|
|
68
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useRef } from "react";
|
|
2
|
-
import { useAnimator } from "./useAnimator.js";
|
|
3
1
|
import { useInitializer } from "use-initializer";
|
|
2
|
+
import { useAnimator } from "./useAnimator.js";
|
|
3
|
+
import { useEffect } from "react";
|
|
4
4
|
/**
|
|
5
5
|
* A value that animates to a target value using a spring animation.
|
|
6
6
|
* This will **not** cause a re-render when the value changes.
|
|
@@ -10,47 +10,17 @@ import { useInitializer } from "use-initializer";
|
|
|
10
10
|
export function useSpringValue(options, onChange) {
|
|
11
11
|
const animator = useAnimator(options.animator);
|
|
12
12
|
const springValue = useInitializer(() => {
|
|
13
|
-
let value = structuredClone(options.initial);
|
|
14
13
|
return {
|
|
15
|
-
|
|
16
|
-
return value;
|
|
17
|
-
},
|
|
18
|
-
set value(newValue) {
|
|
19
|
-
value = newValue;
|
|
20
|
-
onChange(value);
|
|
21
|
-
},
|
|
14
|
+
value: structuredClone(options.initial),
|
|
22
15
|
};
|
|
23
16
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(options.initial)) {
|
|
34
|
-
for (let i = 0; i < options.initial.length; i++) {
|
|
35
|
-
animator.springTo(springValue.value, i, options.target[i], options);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
// assume object, iterate over keys
|
|
40
|
-
for (const key in options.initial) {
|
|
41
|
-
animator.springTo(springValue.value, key, options.target[key], options);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (!afterStepListener.current) {
|
|
45
|
-
afterStepListener.current = animator.onAfterStep.addListener(() => {
|
|
46
|
-
onChange(springValue.value);
|
|
47
|
-
});
|
|
48
|
-
animator.onAllComplete(springValue.value, () => {
|
|
49
|
-
afterStepListener.current?.remove();
|
|
50
|
-
afterStepListener.current = null;
|
|
51
|
-
}, 'once');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
let remove = animator.onChange(springValue, () => {
|
|
19
|
+
onChange(springValue.value);
|
|
20
|
+
}).remove;
|
|
21
|
+
return () => {
|
|
22
|
+
remove();
|
|
23
|
+
};
|
|
24
|
+
}, [springValue, onChange]);
|
|
25
|
+
animator.springTo(springValue, { value: options.target }, options);
|
|
56
26
|
}
|
package/dist/types/Animator.d.ts
CHANGED
|
@@ -1,72 +1,92 @@
|
|
|
1
1
|
import { EventSignal } from "@haxiomic/event-signal";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Tween = 1
|
|
6
|
-
}
|
|
2
|
+
import { IFieldAnimator } from "./IFieldAnimator.js";
|
|
3
|
+
import { SpringParameters } from "./animators/SpringAnimator.js";
|
|
4
|
+
import { EasingStepFn } from "./animators/TweenAnimator.js";
|
|
7
5
|
/**
|
|
8
6
|
* Physically based animation of numeric properties of objects
|
|
9
7
|
*
|
|
10
8
|
* Designed to avoid discontinuities for smooth animation in all conditions
|
|
11
9
|
*/
|
|
12
10
|
export declare class Animator {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
11
|
+
animations: Map<any, Map<FieldKey, FieldAnimation<any, any>>>;
|
|
12
|
+
protected readonly events: {
|
|
13
|
+
beforeStep: EventSignal<{
|
|
14
|
+
dt_s: number;
|
|
15
|
+
}, {
|
|
16
|
+
dt_s: number;
|
|
17
|
+
}>;
|
|
18
|
+
afterStep: EventSignal<{
|
|
19
|
+
dt_s: number;
|
|
20
|
+
}, {
|
|
21
|
+
dt_s: number;
|
|
22
|
+
}>;
|
|
23
|
+
completeField: EventSignal<{
|
|
24
|
+
object: any;
|
|
25
|
+
field: FieldKey;
|
|
26
|
+
}, {
|
|
27
|
+
object: any;
|
|
28
|
+
field: FieldKey;
|
|
29
|
+
}>;
|
|
30
|
+
completeObject: EventSignal<{
|
|
31
|
+
object: any;
|
|
32
|
+
}, {
|
|
33
|
+
object: any;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
protected changeObjectEvents: Map<any, EventSignal<any, any>>;
|
|
37
|
+
protected changeFieldEvents: Map<any, Map<FieldKey, EventSignal<{
|
|
31
38
|
object: any;
|
|
39
|
+
field: any;
|
|
32
40
|
}, {
|
|
33
41
|
object: any;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
springParams: Spring.PhysicsParameters | null;
|
|
39
|
-
tweenParams: Tween.Parameters | null;
|
|
40
|
-
step: TweenStepFn | null;
|
|
41
|
-
velocity: number;
|
|
42
|
-
}>>;
|
|
42
|
+
field: any;
|
|
43
|
+
}>>>;
|
|
44
|
+
protected beforeChange: EventSignal<void, void>;
|
|
45
|
+
protected afterChange: EventSignal<void, void>;
|
|
43
46
|
constructor(onBeforeStep?: (dt_s: number) => void, onAfterStep?: (dt_s: number) => void);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
setTo<Obj, Name extends keyof Obj, T extends Obj[Name]>(object: Obj, field: Name, target: T): void;
|
|
54
|
-
onComplete<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void): {
|
|
47
|
+
setTo<Obj>(object: Obj, target: Partial<Obj>): void;
|
|
48
|
+
animateTo<Obj, Parameters, State, FieldType>(object: Obj, target: Partial<Obj>, animator?: IFieldAnimator<Parameters, State, FieldType>, params?: Parameters | null): void;
|
|
49
|
+
springTo<Obj>(object: Obj, target: Partial<Obj>, params: SpringParameters | null): void;
|
|
50
|
+
customTweenTo<Obj>(object: Obj, target: Partial<Obj>, duration_s: number, easingFn: EasingStepFn): void;
|
|
51
|
+
linearTo<Obj>(object: Obj, target: Partial<Obj>, duration_s: number): void;
|
|
52
|
+
easeInOutTo<Obj>(object: Obj, target: Partial<Obj>, duration_s: number): void;
|
|
53
|
+
easeInTo<Obj>(object: Obj, target: Partial<Obj>, duration_s: number): void;
|
|
54
|
+
easeOutTo<Obj>(object: Obj, target: Partial<Obj>, duration_s: number): void;
|
|
55
|
+
onCompleteField<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void, once?: 'once'): {
|
|
55
56
|
priority: number;
|
|
56
57
|
listener: (event: {
|
|
57
58
|
object: any;
|
|
58
|
-
field:
|
|
59
|
+
field: FieldKey;
|
|
59
60
|
}) => void;
|
|
60
61
|
remove: () => void;
|
|
61
62
|
};
|
|
62
|
-
|
|
63
|
+
onComplete<Obj>(object: Obj, callback: (object: Obj) => void, once?: 'once'): {
|
|
63
64
|
priority: number;
|
|
64
65
|
listener: (event: {
|
|
65
66
|
object: any;
|
|
66
67
|
}) => void;
|
|
67
68
|
remove: () => void;
|
|
68
69
|
};
|
|
69
|
-
|
|
70
|
+
onChangeField<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void): {
|
|
71
|
+
remove: () => void;
|
|
72
|
+
};
|
|
73
|
+
onChange<Obj>(object: Obj, callback: (object: Obj) => void): {
|
|
74
|
+
remove: () => void;
|
|
75
|
+
};
|
|
76
|
+
onBeforeStep(callback: (dt_s: number) => void): {
|
|
77
|
+
priority: number;
|
|
78
|
+
listener: (event: {
|
|
79
|
+
dt_s: number;
|
|
80
|
+
}) => void;
|
|
81
|
+
remove: () => void;
|
|
82
|
+
};
|
|
83
|
+
onAfterStep(callback: (dt_s: number) => void): {
|
|
84
|
+
priority: number;
|
|
85
|
+
listener: (event: {
|
|
86
|
+
dt_s: number;
|
|
87
|
+
}) => void;
|
|
88
|
+
remove: () => void;
|
|
89
|
+
};
|
|
70
90
|
step(dt_s: number): void;
|
|
71
91
|
private t_last;
|
|
72
92
|
tick(): number;
|
|
@@ -91,16 +111,27 @@ export declare class Animator {
|
|
|
91
111
|
* Remove animation for this object and field if it exists
|
|
92
112
|
* Does not change the value of the field
|
|
93
113
|
*/
|
|
94
|
-
remove<T>(object: T, field: keyof T): void;
|
|
114
|
+
remove<T>(object: T, field: keyof T, dispatchComplete?: boolean): void;
|
|
95
115
|
/**
|
|
96
116
|
* Remove all animations for this object
|
|
97
117
|
*/
|
|
98
|
-
removeObject(object: any): void;
|
|
118
|
+
removeObject(object: any, dispatchComplete?: boolean): void;
|
|
99
119
|
/**
|
|
100
120
|
* Remove all animations
|
|
101
121
|
*/
|
|
102
|
-
removeAll(): void;
|
|
103
|
-
|
|
122
|
+
removeAll(dispatchComplete?: boolean): void;
|
|
123
|
+
getState<Obj, Name extends keyof Obj>(object: Obj, field: Name): any;
|
|
124
|
+
protected dispatchChangeObjectEvent(object: any): void;
|
|
125
|
+
protected dispatchChangeFieldEvent<Obj, Name extends keyof Obj>(object: Obj, field: Name): void;
|
|
126
|
+
protected addChangeFieldListener<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void): {
|
|
127
|
+
remove: () => void;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Remove animation from the object and set the field to the target value
|
|
131
|
+
*
|
|
132
|
+
* This completes the animation immediately and dispatches the onComplete event
|
|
133
|
+
*/
|
|
134
|
+
protected setFieldTo<Obj, Name extends keyof Obj, V extends Obj[Name]>(object: Obj, field: Name, targetValue: V): void;
|
|
104
135
|
/**
|
|
105
136
|
* Creates a new map if one doesn't already exist for the given object
|
|
106
137
|
*/
|
|
@@ -108,18 +139,12 @@ export declare class Animator {
|
|
|
108
139
|
/**
|
|
109
140
|
* Creates a new spring if one doesn't already exist for the given object and field
|
|
110
141
|
*/
|
|
111
|
-
private
|
|
112
|
-
}
|
|
113
|
-
export type TweenStepFn = (object: any, field: string | number | symbol, target: number, params: Tween.Parameters, dt_s: number) => void;
|
|
114
|
-
export declare namespace Tween {
|
|
115
|
-
type Parameters = {
|
|
116
|
-
x0: number;
|
|
117
|
-
t0_ms: number;
|
|
118
|
-
duration_s: number;
|
|
119
|
-
};
|
|
120
|
-
function linearStep(object: any, field: string | number | symbol, target: number, params: Tween.Parameters, dt_s: number): void;
|
|
121
|
-
function easeInOutStep(object: any, field: string | number | symbol, target: number, params: Tween.Parameters, dt_s: number): void;
|
|
122
|
-
function easeInStep(object: any, field: string | number | symbol, target: number, params: Tween.Parameters, dt_s: number): void;
|
|
123
|
-
function easeOutStep(object: any, field: string | number | symbol, target: number, params: Tween.Parameters, dt_s: number): void;
|
|
142
|
+
private syncAnimation;
|
|
124
143
|
}
|
|
144
|
+
type FieldAnimation<Params, State> = {
|
|
145
|
+
animator: IFieldAnimator<Params, State, any>;
|
|
146
|
+
state: State;
|
|
147
|
+
params: Params | null;
|
|
148
|
+
};
|
|
149
|
+
type FieldKey = string | number | symbol;
|
|
125
150
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare enum StepResult {
|
|
2
|
+
Continue = 0,// continue stepping
|
|
3
|
+
Complete = 1
|
|
4
|
+
}
|
|
5
|
+
export interface IFieldAnimator<Params, State, FieldType> {
|
|
6
|
+
createState<Name extends keyof Obj, Obj extends Record<Name, FieldType>>(object: Obj, field: Name, target: Obj[Name], params: Params | null): State;
|
|
7
|
+
updateState<Name extends keyof Obj, Obj extends Record<Name, FieldType>>(state: State, object: Obj, field: Name, target: Obj[Name], params: Params | null): void;
|
|
8
|
+
step<Name extends keyof Obj, Obj extends Record<Name, FieldType>>(state: State, object: Obj, field: Name, params: Params, dt_s: number): StepResult;
|
|
9
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { IFieldAnimator } from "../IFieldAnimator.js";
|
|
2
|
+
export declare const SpringAnimator: IFieldAnimator<SpringParameters, SpringState, number>;
|
|
1
3
|
/**
|
|
2
4
|
* Spring
|
|
3
5
|
*
|
|
@@ -12,10 +14,16 @@ type UnderdampedParameters = {
|
|
|
12
14
|
duration_s: number;
|
|
13
15
|
/**
|
|
14
16
|
* How soft / bouncy the spring, at 0 there is no bounce and decay is exponential, from 0 to infinity the spring will overshoot its target while decaying
|
|
15
|
-
* It can be
|
|
17
|
+
* It can be thought of roughly the number of oscillations it will take to reach the target
|
|
16
18
|
*/
|
|
17
19
|
bounce: number;
|
|
18
20
|
};
|
|
21
|
+
type SpringState = {
|
|
22
|
+
x: number;
|
|
23
|
+
targetX: number;
|
|
24
|
+
v: number;
|
|
25
|
+
physicsParameters: Spring.PhysicsParameters;
|
|
26
|
+
};
|
|
19
27
|
export type SpringParameters = ExponentialParameters | UnderdampedParameters | Spring.PhysicsParameters;
|
|
20
28
|
export declare namespace Spring {
|
|
21
29
|
type PhysicsParameters = {
|
|
@@ -37,6 +45,8 @@ export declare namespace Spring {
|
|
|
37
45
|
* @param dt_s
|
|
38
46
|
* @param state
|
|
39
47
|
* @param parameters
|
|
48
|
+
*
|
|
49
|
+
* If parameters are NaN or infinite, the spring will skip to the target
|
|
40
50
|
*/
|
|
41
51
|
function stepSpring(dt_s: number, state: {
|
|
42
52
|
x: number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IFieldAnimator } from "../IFieldAnimator.js";
|
|
2
|
+
export type TweenParameters = {
|
|
3
|
+
duration_s: number;
|
|
4
|
+
easingFn: EasingStepFn;
|
|
5
|
+
};
|
|
6
|
+
export declare const TweenAnimator: IFieldAnimator<TweenParameters, TweenState, number>;
|
|
7
|
+
type TweenState = {
|
|
8
|
+
x0: number;
|
|
9
|
+
t0_ms: number;
|
|
10
|
+
target: number;
|
|
11
|
+
duration_s: number;
|
|
12
|
+
easingFn: EasingStepFn;
|
|
13
|
+
velocity: number;
|
|
14
|
+
};
|
|
15
|
+
type FieldKey = string | number | symbol;
|
|
16
|
+
export type EasingStepFn = (object: any, field: FieldKey, target: number, state: TweenState, dt_s: number) => void;
|
|
17
|
+
export declare function linearStep(object: any, field: FieldKey, target: number, params: TweenState, dt_s: number): void;
|
|
18
|
+
export declare function easeInOutStep(object: any, field: FieldKey, target: number, params: TweenState, dt_s: number): void;
|
|
19
|
+
export declare function easeInStep(object: any, field: FieldKey, target: number, params: TweenState, dt_s: number): void;
|
|
20
|
+
export declare function easeOutStep(object: any, field: FieldKey, target: number, params: TweenState, dt_s: number): void;
|
|
21
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Animator } from "../Animator.js";
|
|
2
|
-
import { SpringParameters } from "
|
|
2
|
+
import { SpringParameters } from "src/animators/SpringAnimator.js";
|
|
3
3
|
/**
|
|
4
4
|
* A value that animates to a target value using a spring animation.
|
|
5
5
|
* This **will** cause a re-render when the value changes.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Animator } from "../Animator.js";
|
|
2
|
-
import { SpringParameters } from "
|
|
2
|
+
import { SpringParameters } from "src/animators/SpringAnimator.js";
|
|
3
3
|
/**
|
|
4
4
|
* A value that animates to a target value using a spring animation.
|
|
5
5
|
* This will **not** cause a re-render when the value changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "physics-animator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"author": "haxiomic (George Corney)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A TypeScript animation system grounded in physics with three.js and react support.",
|
|
@@ -39,17 +39,9 @@
|
|
|
39
39
|
"use-initializer": "^1.1.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"
|
|
43
|
-
"react": ">=18.2.0",
|
|
44
|
-
"three": "x.x.x"
|
|
42
|
+
"react": ">=18.2.0"
|
|
45
43
|
},
|
|
46
44
|
"peerDependenciesMeta": {
|
|
47
|
-
"@types/three": {
|
|
48
|
-
"optional": true
|
|
49
|
-
},
|
|
50
|
-
"three": {
|
|
51
|
-
"optional": true
|
|
52
|
-
},
|
|
53
45
|
"react": {
|
|
54
46
|
"optional": true
|
|
55
47
|
}
|