Skip to content

Commit bcfe1eb

Browse files
committed
main 🧊 add use parallax, add use device orientation, add use screen orientation
1 parent 5d7de03 commit bcfe1eb

File tree

10 files changed

+508
-12
lines changed

10 files changed

+508
-12
lines changed

‎src/hooks/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './useDebounceCallback/useDebounceCallback';
1111
export * from './useDebounceValue/useDebounceValue';
1212
export * from './useDefault/useDefault';
1313
export * from './useDeviceMotion/useDeviceMotion';
14+
export * from './useDeviceOrientation/useDeviceOrientation';
1415
export * from './useDidUpdate/useDidUpdate';
1516
export * from './useDisclosure/useDisclosure';
1617
export * from './useDocumentEvent/useDocumentEvent';
@@ -76,6 +77,7 @@ export * from './useRenderCount/useRenderCount';
7677
export * from './useRenderInfo/useRenderInfo';
7778
export * from './useRerender/useRerender';
7879
export * from './useResizeObserver/useResizeObserver';
80+
export * from './useScreenOrientation/useScreenOrientation';
7981
export * from './useScript/useScript';
8082
export * from './useSessionStorage/useSessionStorage';
8183
export * from './useSet/useSet';

‎src/hooks/useDeviceMotion/useDeviceMotion.demo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { useDeviceMotion } from './useDeviceMotion';
22

33
const Demo = () => {
4-
const deviceMotionData = useDeviceMotion();
4+
const deviceMotion = useDeviceMotion();
55

66
return (
77
<pre lang='json'>
88
<b>Device motion data:</b>
9-
<p>{JSON.stringify(deviceMotionData, null, 2)}</p>
9+
<p>{JSON.stringify(deviceMotion, null, 2)}</p>
1010
</pre>
1111
);
1212
};

‎src/hooks/useDeviceMotion/useDeviceMotion.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ export interface UseDeviceMotionReturn {
1010
}
1111

1212
export interface UseDeviceMotionParams {
13+
/** The delay in milliseconds */
1314
delay?: number;
15+
/** The callback function to be invoked */
1416
callback?: (event: DeviceMotionEvent) => void;
17+
/** Whether to enable the hook */
1518
enabled?: boolean;
1619
}
1720

@@ -31,7 +34,7 @@ export interface UseDeviceMotionParams {
3134
export const useDeviceMotion = (params?: UseDeviceMotionParams) => {
3235
const enabled = params?.enabled ?? true;
3336
const delay = params?.delay ?? 1000;
34-
const [deviceMotionData, setDeviceMotionData] = useState<UseDeviceMotionReturn>({
37+
const [value, setValue] = useState<UseDeviceMotionReturn>({
3538
interval: 0,
3639
rotationRate: { alpha: null, beta: null, gamma: null },
3740
acceleration: { x: null, y: null, z: null },
@@ -45,18 +48,18 @@ export const useDeviceMotion = (params?: UseDeviceMotionParams) => {
4548

4649
const onDeviceMotion = throttle<[DeviceMotionEvent]>((event) => {
4750
internalCallbackRef.current?.(event);
48-
setDeviceMotionData({
51+
setValue({
4952
interval: event.interval,
5053
rotationRate: {
51-
...deviceMotionData.rotationRate,
54+
...value.rotationRate,
5255
...event.rotationRate
5356
},
5457
acceleration: {
55-
...deviceMotionData.acceleration,
58+
...value.acceleration,
5659
...event.acceleration
5760
},
5861
accelerationIncludingGravity: {
59-
...deviceMotionData.accelerationIncludingGravity,
62+
...value.accelerationIncludingGravity,
6063
...event.accelerationIncludingGravity
6164
}
6265
});
@@ -69,5 +72,5 @@ export const useDeviceMotion = (params?: UseDeviceMotionParams) => {
6972
};
7073
}, [delay, enabled]);
7174

72-
return deviceMotionData;
75+
return value;
7376
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useDeviceOrientation } from './useDeviceOrientation';
2+
3+
const Demo = () => {
4+
const deviceOrientation = useDeviceOrientation();
5+
6+
return (
7+
<pre lang='json'>
8+
<b>Device orientation data:</b>
9+
<p>{JSON.stringify(deviceOrientation.value, null, 2)}</p>
10+
</pre>
11+
);
12+
};
13+
14+
export default Demo;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useEffect, useState } from 'react';
2+
3+
/* The use device orientation value type */
4+
export interface UseDeviceOrientationValue {
5+
/** A number representing the motion of the device around the z axis, express in degrees with values ranging from 0 to 360 */
6+
alpha: number | null
7+
/** A number representing the motion of the device around the x axis, express in degrees with values ranging from -180 to 180 */
8+
beta: number | null
9+
/** A number representing the motion of the device around the y axis, express in degrees with values ranging from -90 to 90 */
10+
gamma: number | null
11+
/** The current absolute value */
12+
absolute: boolean
13+
}
14+
15+
/* The use device orientation return type */
16+
export interface UseDeviceOrientationReturn {
17+
/** Whether the device orientation is supported */
18+
supported: boolean
19+
/** The current device orientation value */
20+
value: UseDeviceOrientationValue
21+
}
22+
23+
/**
24+
* @name useDeviceOrientation
25+
* @description - Hook that provides the current device orientation
26+
* @category Sensors
27+
*
28+
* @returns {UseDeviceOrientationReturn} The current device orientation
29+
*
30+
* @example
31+
* const { supported, value } = useDeviceOrientation();
32+
*/
33+
export const useDeviceOrientation = (): UseDeviceOrientationReturn => {
34+
const supported = window && 'DeviceOrientationEvent' in window;
35+
36+
const [value, setValue] = useState<UseDeviceOrientationValue>({
37+
alpha: null,
38+
beta: null,
39+
gamma: null,
40+
absolute: false
41+
});
42+
43+
useEffect(() => {
44+
if (!supported) return;
45+
46+
const onDeviceOrientation = (event: DeviceOrientationEvent) =>
47+
setValue({
48+
alpha: event.alpha,
49+
beta: event.beta,
50+
gamma: event.gamma,
51+
absolute: event.absolute
52+
});
53+
54+
window.addEventListener('deviceorientation', onDeviceOrientation);
55+
return () => {
56+
window.removeEventListener('deviceorientation', onDeviceOrientation);
57+
};
58+
}, []);
59+
60+
return {
61+
supported,
62+
value
63+
};
64+
};

‎src/hooks/useMouse/useMouse.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import { useEffect, useState } from 'react';
44
import { getElement } from '@/utils/helpers';
55

66
/** The use mouse target element type */
7-
type UseMouseTarget = RefObject<Element | null | undefined> | (() => Element) | Element;
7+
export type UseMouseTarget = RefObject<Element | null | undefined> | (() => Element) | Element;
88

99
/** The use mouse return type */
1010
export interface UseMouseReturn {
1111
/** The current mouse x position */
1212
x: number;
1313
/** The current mouse y position */
1414
y: number;
15+
/** The current element */
16+
element: Element;
1517
/** The current element x position */
1618
elementX: number;
1719
/** The current element y position */
@@ -63,6 +65,7 @@ export const useMouse = ((...params: any[]) => {
6365
const [internalRef, setInternalRef] = useState<Element>();
6466

6567
useEffect(() => {
68+
console.log('@@@@@', target);
6669
if (!target && !internalRef) return;
6770
const onMouseMove = (event: MouseEvent) => {
6871
const element = (target ? getElement(target) : internalRef) as Element;
@@ -91,15 +94,15 @@ export const useMouse = ((...params: any[]) => {
9194
};
9295

9396
document.addEventListener('mousemove', onMouseMove);
94-
9597
return () => {
9698
document.removeEventListener('mousemove', onMouseMove);
9799
};
98100
}, [internalRef, target]);
99101

100-
if (target) return value;
102+
if (target) return { ...value, element: target ?? internalRef };
101103
return {
102104
ref: setInternalRef,
103-
...value
105+
...value,
106+
element: target ?? internalRef
104107
};
105108
}) as UseMouse;
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import type { CSSProperties } from 'react';
2+
3+
import { useParallax } from './useParallax';
4+
5+
const Demo = () => {
6+
const parallax = useParallax<HTMLDivElement>();
7+
8+
const layerBase: CSSProperties = {
9+
position: 'absolute',
10+
height: '100%',
11+
width: '100%',
12+
transition: '.3s ease-out all'
13+
};
14+
15+
const layer0 = {
16+
...layerBase,
17+
transform: `translateX(${parallax.value.tilt * 10}px) translateY(${
18+
parallax.value.roll * 10
19+
}px)`
20+
};
21+
22+
const layer1 = {
23+
...layerBase,
24+
transform: `translateX(${parallax.value.tilt * 20}px) translateY(${
25+
parallax.value.roll * 20
26+
}px)`
27+
};
28+
29+
const layer2 = {
30+
...layerBase,
31+
transform: `translateX(${parallax.value.tilt * 30}px) translateY(${
32+
parallax.value.roll * 30
33+
}px)`
34+
};
35+
36+
const layer3 = {
37+
...layerBase,
38+
transform: `translateX(${parallax.value.tilt * 40}px) translateY(${
39+
parallax.value.roll * 40
40+
}px)`
41+
};
42+
43+
const cardStyle = {
44+
background: '#fff',
45+
height: '18rem',
46+
width: '14rem',
47+
borderRadius: '5px',
48+
border: '1px solid #cdcdcd',
49+
overflow: 'hidden',
50+
transition: '.3s ease-out all',
51+
boxShadow: '0 0 20px 0 rgba(255, 255, 255, 0.25)',
52+
transform: `rotateX(${parallax.value.roll * 20}deg) rotateY(${
53+
parallax.value.tilt * 20
54+
}deg)`
55+
};
56+
57+
const containerStyle: CSSProperties = {
58+
margin: '3em auto',
59+
perspective: '200px'
60+
};
61+
62+
const cardContentStyle: CSSProperties = {
63+
overflow: 'hidden',
64+
fontSize: '6rem',
65+
position: 'absolute',
66+
top: 'calc(50% - 1em)',
67+
left: 'calc(50% - 1em)',
68+
height: '2em',
69+
width: '2em',
70+
margin: 'auto'
71+
};
72+
73+
const targetStyle: CSSProperties = {
74+
display: 'flex',
75+
flexDirection: 'column',
76+
justifyContent: 'center',
77+
minHeight: '500px',
78+
transition: '.3s ease-out all'
79+
};
80+
81+
return (
82+
<div ref={parallax.ref} style={targetStyle}>
83+
<pre lang='json'>
84+
<b>Parallax data:</b>
85+
<p>{JSON.stringify(parallax.value, null, 2)}</p>
86+
</pre>
87+
<div style={containerStyle}>
88+
<div style={cardStyle}>
89+
<div style={cardContentStyle}>
90+
<img
91+
style={layer0}
92+
src='https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_3.png'
93+
alt='layer0'
94+
/>
95+
<img
96+
style={layer1}
97+
src='https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_2.png'
98+
alt='layer1'
99+
/>
100+
<img
101+
style={layer2}
102+
src='https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_1.png'
103+
alt='layer2'
104+
/>
105+
<img
106+
style={layer3}
107+
src='https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_0.png'
108+
alt='layer3'
109+
/>
110+
</div>
111+
</div>
112+
</div>
113+
<div>
114+
Credit of images to{' '}
115+
<a
116+
href='https://codepen.io/jaromvogel'
117+
target='__blank'
118+
>Jarom Vogel
119+
</a>
120+
</div>
121+
</div>
122+
);
123+
};
124+
125+
export default Demo;

0 commit comments

Comments
 (0)