physics-animator 0.16.0 → 1.0.0
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 +7 -6
- package/dist/cjs/react/useSpringState.js +6 -7
- package/dist/cjs/react/useSpringValue.js +11 -30
- package/dist/esm/react/useSpringState.js +6 -7
- package/dist/esm/react/useSpringValue.js +11 -30
- package/dist/types/Animator.d.ts +4 -29
- package/dist/types/react/useSpringState.d.ts +3 -6
- package/dist/types/react/useSpringValue.d.ts +16 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,19 +12,20 @@ Why use this over other animation systems?
|
|
|
12
12
|
|
|
13
13
|
This library focuses on simplicity and correctness – I've generally run into design troubles with popular animation libraries like framer motion: for example complex framer animations become convoluted and don't correctly handled interruptions without discontinuities in velocity
|
|
14
14
|
|
|
15
|
-
For example in react, to animate opacity we could do
|
|
15
|
+
For example in react, to animate DOM opacity we could do
|
|
16
16
|
|
|
17
17
|
```tsx
|
|
18
18
|
useSpringValue(
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
1.0, // target
|
|
20
|
+
{ duration_s: 0.8 },
|
|
21
|
+
value => el.style.opacity = value // onChange
|
|
21
22
|
)
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
Or via state
|
|
25
26
|
|
|
26
27
|
```tsx
|
|
27
|
-
const opacitySpring = useSpringState({
|
|
28
|
+
const opacitySpring = useSpringState(opacity, { duration_s: 0.8 })
|
|
28
29
|
|
|
29
30
|
return <div style={{ opacity: opacitySpring }} />
|
|
30
31
|
```
|
|
@@ -32,8 +33,8 @@ return <div style={{ opacity: opacitySpring }} />
|
|
|
32
33
|
It works with arrays and objects
|
|
33
34
|
|
|
34
35
|
```tsx
|
|
35
|
-
const rgb = useSpringState(
|
|
36
|
-
const xy = useSpringState({
|
|
36
|
+
const rgb = useSpringState([1, 0, 0], { initial: [0, 0, 0], duration_s: 0.8 })
|
|
37
|
+
const xy = useSpringState({x: mouse.x, y: mouse.y})
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
Outside of react we use the animator object
|
|
@@ -14,12 +14,11 @@ const useSpringValue_js_1 = require("./useSpringValue.js");
|
|
|
14
14
|
*
|
|
15
15
|
* See {@link useSpringValue} for a version that does not cause re-renders.
|
|
16
16
|
*/
|
|
17
|
-
function useSpringState(options
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}, setState);
|
|
17
|
+
function useSpringState(value, options = {
|
|
18
|
+
duration_s: 0.5,
|
|
19
|
+
}) {
|
|
20
|
+
// type N = WidenNumber<T>;
|
|
21
|
+
const [state, setState] = (0, react_1.useState)(value);
|
|
22
|
+
(0, useSpringValue_js_1.useSpringValue)(value, options, setState);
|
|
24
23
|
return state;
|
|
25
24
|
}
|
|
@@ -4,35 +4,16 @@ exports.useSpringValue = useSpringValue;
|
|
|
4
4
|
const use_initializer_1 = require("use-initializer");
|
|
5
5
|
const useAnimator_js_1 = require("./useAnimator.js");
|
|
6
6
|
const react_1 = require("react");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* { initial: 0, target: 1, duration_s: 0.8 },
|
|
15
|
-
* // onChange
|
|
16
|
-
* value => el.style.opacity = value
|
|
17
|
-
* );
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* See {@link useSpringState} for a version that does cause re-renders.
|
|
21
|
-
*/
|
|
22
|
-
function useSpringValue(options, onChange) {
|
|
7
|
+
function useSpringValue(value, optionsOrOnChange, maybeOnChange) {
|
|
8
|
+
const options = typeof optionsOrOnChange === 'function'
|
|
9
|
+
? { duration_s: 0.5 }
|
|
10
|
+
: optionsOrOnChange;
|
|
11
|
+
const onChange = typeof optionsOrOnChange === 'function'
|
|
12
|
+
? optionsOrOnChange
|
|
13
|
+
: maybeOnChange;
|
|
23
14
|
const animator = (0, useAnimator_js_1.useAnimator)(options.animator);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
(0, react_1.useEffect)(() => {
|
|
30
|
-
let remove = animator.onChange(springValue, () => {
|
|
31
|
-
onChange(springValue.value);
|
|
32
|
-
}).remove;
|
|
33
|
-
return () => {
|
|
34
|
-
remove();
|
|
35
|
-
};
|
|
36
|
-
}, [springValue, onChange]);
|
|
37
|
-
animator.springTo(springValue, { value: options.target }, options);
|
|
15
|
+
const springObject = (0, use_initializer_1.useInitializer)(() => ({ value: options.initial ?? value }));
|
|
16
|
+
(0, react_1.useEffect)(() => animator.onChange(springObject, () => onChange(springObject.value)).remove // return the cleanup function
|
|
17
|
+
, [springObject, onChange]);
|
|
18
|
+
animator.springTo(springObject, { value }, options);
|
|
38
19
|
}
|
|
@@ -11,12 +11,11 @@ import { useSpringValue } from "./useSpringValue.js";
|
|
|
11
11
|
*
|
|
12
12
|
* See {@link useSpringValue} for a version that does not cause re-renders.
|
|
13
13
|
*/
|
|
14
|
-
export function useSpringState(options
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}, setState);
|
|
14
|
+
export function useSpringState(value, options = {
|
|
15
|
+
duration_s: 0.5,
|
|
16
|
+
}) {
|
|
17
|
+
// type N = WidenNumber<T>;
|
|
18
|
+
const [state, setState] = useState(value);
|
|
19
|
+
useSpringValue(value, options, setState);
|
|
21
20
|
return state;
|
|
22
21
|
}
|
|
@@ -1,35 +1,16 @@
|
|
|
1
1
|
import { useInitializer } from "use-initializer";
|
|
2
2
|
import { useAnimator } from "./useAnimator.js";
|
|
3
3
|
import { useEffect } from "react";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* { initial: 0, target: 1, duration_s: 0.8 },
|
|
12
|
-
* // onChange
|
|
13
|
-
* value => el.style.opacity = value
|
|
14
|
-
* );
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* See {@link useSpringState} for a version that does cause re-renders.
|
|
18
|
-
*/
|
|
19
|
-
export function useSpringValue(options, onChange) {
|
|
4
|
+
export function useSpringValue(value, optionsOrOnChange, maybeOnChange) {
|
|
5
|
+
const options = typeof optionsOrOnChange === 'function'
|
|
6
|
+
? { duration_s: 0.5 }
|
|
7
|
+
: optionsOrOnChange;
|
|
8
|
+
const onChange = typeof optionsOrOnChange === 'function'
|
|
9
|
+
? optionsOrOnChange
|
|
10
|
+
: maybeOnChange;
|
|
20
11
|
const animator = useAnimator(options.animator);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
let remove = animator.onChange(springValue, () => {
|
|
28
|
-
onChange(springValue.value);
|
|
29
|
-
}).remove;
|
|
30
|
-
return () => {
|
|
31
|
-
remove();
|
|
32
|
-
};
|
|
33
|
-
}, [springValue, onChange]);
|
|
34
|
-
animator.springTo(springValue, { value: options.target }, options);
|
|
12
|
+
const springObject = useInitializer(() => ({ value: options.initial ?? value }));
|
|
13
|
+
useEffect(() => animator.onChange(springObject, () => onChange(springObject.value)).remove // return the cleanup function
|
|
14
|
+
, [springObject, onChange]);
|
|
15
|
+
animator.springTo(springObject, { value }, options);
|
|
35
16
|
}
|
package/dist/types/Animator.d.ts
CHANGED
|
@@ -53,21 +53,8 @@ export declare class Animator {
|
|
|
53
53
|
easeInOutTo<Obj>(object: Obj, target: Partial<Public<Obj>>, duration_s: number): void;
|
|
54
54
|
easeInTo<Obj>(object: Obj, target: Partial<Public<Obj>>, duration_s: number): void;
|
|
55
55
|
easeOutTo<Obj>(object: Obj, target: Partial<Public<Obj>>, duration_s: number): void;
|
|
56
|
-
onCompleteField<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void, once?: 'once'):
|
|
57
|
-
|
|
58
|
-
listener: (event: {
|
|
59
|
-
object: any;
|
|
60
|
-
field: FieldKey;
|
|
61
|
-
}) => void;
|
|
62
|
-
remove: () => void;
|
|
63
|
-
};
|
|
64
|
-
onComplete<Obj>(object: Obj, callback: (object: Obj) => void, once?: 'once'): {
|
|
65
|
-
priority: number;
|
|
66
|
-
listener: (event: {
|
|
67
|
-
object: any;
|
|
68
|
-
}) => void;
|
|
69
|
-
remove: () => void;
|
|
70
|
-
};
|
|
56
|
+
onCompleteField<Obj, Name extends keyof Obj>(object: Obj, field: Name, callback: (object: Obj, field: Name) => void, once?: 'once'): EventSignal.Listener;
|
|
57
|
+
onComplete<Obj>(object: Obj, callback: (object: Obj) => void, once?: 'once'): EventSignal.Listener;
|
|
71
58
|
/**
|
|
72
59
|
* Execute a callback when a specific field of an object is changed by the animator
|
|
73
60
|
*/
|
|
@@ -80,20 +67,8 @@ export declare class Animator {
|
|
|
80
67
|
onChange<Obj>(object: Obj, callback: (object: Obj) => void): {
|
|
81
68
|
remove: () => void;
|
|
82
69
|
};
|
|
83
|
-
onBeforeStep(callback: (dt_s: number) => void):
|
|
84
|
-
|
|
85
|
-
listener: (event: {
|
|
86
|
-
dt_s: number;
|
|
87
|
-
}) => void;
|
|
88
|
-
remove: () => void;
|
|
89
|
-
};
|
|
90
|
-
onAfterStep(callback: (dt_s: number) => void): {
|
|
91
|
-
priority: number;
|
|
92
|
-
listener: (event: {
|
|
93
|
-
dt_s: number;
|
|
94
|
-
}) => void;
|
|
95
|
-
remove: () => void;
|
|
96
|
-
};
|
|
70
|
+
onBeforeStep(callback: (dt_s: number) => void): EventSignal.Listener;
|
|
71
|
+
onAfterStep(callback: (dt_s: number) => void): EventSignal.Listener;
|
|
97
72
|
step(dt_s: number): void;
|
|
98
73
|
private t_last;
|
|
99
74
|
tick(): number;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Animator } from "../Animator.js";
|
|
2
2
|
import { SpringParameters } from "../animators/SpringAnimator.js";
|
|
3
|
-
type WidenNumber<T> = T extends number ? number : T;
|
|
4
3
|
/**
|
|
5
4
|
* A value that animates to a target value using a spring animation.
|
|
6
5
|
* This **will** cause a re-render when the value changes.
|
|
@@ -14,9 +13,7 @@ type WidenNumber<T> = T extends number ? number : T;
|
|
|
14
13
|
*/
|
|
15
14
|
export declare function useSpringState<T extends number | number[] | {
|
|
16
15
|
[field: PropertyKey]: number;
|
|
17
|
-
}>(
|
|
16
|
+
}>(value: T, options?: {
|
|
18
17
|
animator?: Animator;
|
|
19
|
-
initial
|
|
20
|
-
|
|
21
|
-
} & SpringParameters): WidenNumber<T>;
|
|
22
|
-
export {};
|
|
18
|
+
initial?: T;
|
|
19
|
+
} & SpringParameters): T;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Animator } from "../Animator.js";
|
|
2
2
|
import { SpringParameters } from "../animators/SpringAnimator.js";
|
|
3
|
+
type SpringOptions<T> = {
|
|
4
|
+
animator?: Animator;
|
|
5
|
+
initial?: T;
|
|
6
|
+
} & SpringParameters;
|
|
3
7
|
/**
|
|
4
8
|
* A value that animates to a target value using a spring animation.
|
|
5
9
|
* This will **not** cause a re-render when the value changes.
|
|
@@ -7,18 +11,24 @@ import { SpringParameters } from "../animators/SpringAnimator.js";
|
|
|
7
11
|
* Usage example:
|
|
8
12
|
* ```tsx
|
|
9
13
|
* useSpringValue(
|
|
10
|
-
*
|
|
14
|
+
* 1,
|
|
15
|
+
* { initial: 0, duration_s: 0.8 },
|
|
11
16
|
* // onChange
|
|
12
17
|
* value => el.style.opacity = value
|
|
13
18
|
* );
|
|
14
19
|
* ```
|
|
15
20
|
*
|
|
21
|
+
* Or with default options:
|
|
22
|
+
* ```tsx
|
|
23
|
+
* useSpringValue(1, value => el.style.opacity = value);
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
16
26
|
* See {@link useSpringState} for a version that does cause re-renders.
|
|
17
27
|
*/
|
|
18
28
|
export declare function useSpringValue<T extends number | number[] | {
|
|
19
29
|
[field: PropertyKey]: number;
|
|
20
|
-
}>(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
30
|
+
}>(value: T, onChange: (value: T) => void): void;
|
|
31
|
+
export declare function useSpringValue<T extends number | number[] | {
|
|
32
|
+
[field: PropertyKey]: number;
|
|
33
|
+
}>(value: T, options: SpringOptions<T>, onChange: (value: T) => void): void;
|
|
34
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "physics-animator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
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.",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"typescript": "^5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@haxiomic/event-signal": "^1.
|
|
50
|
+
"@haxiomic/event-signal": "^1.2.0",
|
|
51
51
|
"use-initializer": "^1.1.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|