Skip to content

Commit 4933326

Browse files
authored
Merge pull request #229 from siberiacancode/#202
[feat]: useDeviceMotion
2 parents 54ff991 + 74c3cd8 commit 4933326

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export * from './useCssVar/useCssVar';
1010
export * from './useDebounceCallback/useDebounceCallback';
1111
export * from './useDebounceValue/useDebounceValue';
1212
export * from './useDefault/useDefault';
13+
export * from './useDeviceMotion/useDeviceMotion';
1314
export * from './useDidUpdate/useDidUpdate';
1415
export * from './useDisclosure/useDisclosure';
1516
export * from './useDocumentEvent/useDocumentEvent';
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useDeviceMotion } from './useDeviceMotion';
2+
3+
const Demo = () => {
4+
const deviceMotionData = useDeviceMotion();
5+
6+
return (
7+
<pre lang='json'>
8+
<b>Device motion data:</b>
9+
<p>{JSON.stringify(deviceMotionData, null, 2)}</p>
10+
</pre>
11+
);
12+
};
13+
14+
export default Demo;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useEffect, useRef, useState } from 'react';
2+
3+
import { throttle } from '@/utils/helpers';
4+
5+
export interface UseDeviceMotionReturn {
6+
interval: DeviceMotionEvent['interval'];
7+
acceleration: DeviceMotionEventAcceleration
8+
accelerationIncludingGravity: DeviceMotionEventAcceleration
9+
rotationRate: DeviceMotionEventRotationRate
10+
}
11+
12+
export interface UseDeviceMotionParams {
13+
delay?: number;
14+
callback?: (event: DeviceMotionEvent) => void;
15+
enabled?: boolean;
16+
}
17+
18+
/**
19+
* @name useDeviceMotion
20+
* @description Hook that work with device motion
21+
* @category Utilities
22+
*
23+
* @param {number} [delay=1000] The delay in milliseconds
24+
* @param {(event: DeviceMotionEvent) => void} [callback] The callback function to be invoked
25+
* @param {boolean} [enabled=true] Whether to enable the hook
26+
* @returns {UseDeviceMotionReturn} The device motion data and interval
27+
*
28+
* @example
29+
* const { interval, rotationRate, acceleration, accelerationIncludingGravity } = useDeviceMotion();
30+
*/
31+
export const useDeviceMotion = (params?: UseDeviceMotionParams) => {
32+
const enabled = params?.enabled ?? true;
33+
const delay = params?.delay ?? 1000;
34+
const [deviceMotionData, setDeviceMotionData] = useState<UseDeviceMotionReturn>({
35+
interval: 0,
36+
rotationRate: { alpha: null, beta: null, gamma: null },
37+
acceleration: { x: null, y: null, z: null },
38+
accelerationIncludingGravity: { x: null, y: null, z: null }
39+
});
40+
const internalCallbackRef = useRef(params?.callback);
41+
internalCallbackRef.current = params?.callback;
42+
43+
useEffect(() => {
44+
if (!enabled) return;
45+
46+
const onDeviceMotion = throttle<[DeviceMotionEvent]>((event) => {
47+
internalCallbackRef.current?.(event);
48+
setDeviceMotionData({
49+
interval: event.interval,
50+
rotationRate: {
51+
...deviceMotionData.rotationRate,
52+
...event.rotationRate
53+
},
54+
acceleration: {
55+
...deviceMotionData.acceleration,
56+
...event.acceleration
57+
},
58+
accelerationIncludingGravity: {
59+
...deviceMotionData.accelerationIncludingGravity,
60+
...event.accelerationIncludingGravity
61+
}
62+
});
63+
}, delay);
64+
65+
window.addEventListener('devicemotion', onDeviceMotion);
66+
67+
return () => {
68+
window.removeEventListener('devicemotion', onDeviceMotion);
69+
};
70+
}, [delay, enabled]);
71+
72+
return deviceMotionData;
73+
};

0 commit comments

Comments
 (0)