1
1
import { DeviceOrientationControls } from "three/examples/jsm/controls/DeviceOrientationControls" ;
2
- import { MutableRefObject , ReactNode , useEffect , useState } from "react" ;
2
+ import {
3
+ MutableRefObject ,
4
+ ReactNode ,
5
+ useEffect ,
6
+ useRef ,
7
+ useState ,
8
+ } from "react" ;
3
9
import { useFrame , useThree } from "react-three-fiber" ;
4
- import { Quaternion , Vector3 } from "three" ;
10
+ import { Quaternion , Vector2 , Vector3 } from "three" ;
11
+ import { config , useSpring } from "react-spring" ;
12
+ import {
13
+ Touch ,
14
+ DefaultTouch ,
15
+ getCurrentTouch ,
16
+ tappedNipple ,
17
+ } from "../utils/touch" ;
18
+ import { getSpringValues } from "../utils/spring" ;
19
+
20
+ const ALPHA_SENSITIVITY = 0.008 ;
5
21
6
22
type GyroControlsProps = {
7
23
quaternion : MutableRefObject < Quaternion > ;
@@ -15,6 +31,8 @@ type GyroControlsProps = {
15
31
* A required fallback component will be used in the place of the gyroscope
16
32
* controls until they are accepted and in use.
17
33
*
34
+ * Some code sampled from TouchFPSCamera.ts
35
+ *
18
36
* @param props
19
37
* @constructor
20
38
*/
@@ -26,6 +44,14 @@ export const GyroControls = (props: GyroControlsProps) => {
26
44
const [ controls , setControls ] = useState < DeviceOrientationControls > ( ) ;
27
45
const [ enableGyro , setEnableGyro ] = useState ( false ) ;
28
46
47
+ // dragging for y axis offset
48
+ const touchStartPos = useRef < Touch > ( DefaultTouch ) ;
49
+ const currentOffset = useRef ( 0 ) ;
50
+ const [ spring , setSpring ] = useSpring ( ( ) => ( {
51
+ a : [ 0 ] ,
52
+ config : { ...config . default , precision : 0.001 } ,
53
+ } ) ) ;
54
+
29
55
// try to prompt user for device controls
30
56
useEffect ( ( ) => {
31
57
if ( ! controls ) {
@@ -52,6 +78,8 @@ export const GyroControls = (props: GyroControlsProps) => {
52
78
}
53
79
54
80
if ( controls ) {
81
+ const [ a ] = getSpringValues ( spring ) ;
82
+ controls . alphaOffset = - a * ALPHA_SENSITIVITY ;
55
83
controls . update ( ) ;
56
84
quaternion . current = camera . quaternion ;
57
85
}
@@ -62,6 +90,60 @@ export const GyroControls = (props: GyroControlsProps) => {
62
90
}
63
91
} ) ;
64
92
93
+ // touch move scripts
94
+ const onTouchStart = ( ev : TouchEvent ) => {
95
+ if ( touchStartPos . current . id !== - 1 ) {
96
+ return ;
97
+ }
98
+
99
+ if ( tappedNipple ( ev ) ) {
100
+ touchStartPos . current = DefaultTouch ;
101
+ return ;
102
+ }
103
+
104
+ // get last in list (most recent touch) to not confuse with movement
105
+ const touchIndex = ev . touches . length - 1 ;
106
+ const { clientX, clientY, identifier : id } = ev . touches [ touchIndex ] ;
107
+
108
+ touchStartPos . current = { pos : new Vector2 ( clientX , clientY ) , id } ;
109
+ } ;
110
+
111
+ const onTouchMove = ( ev : TouchEvent ) => {
112
+ const touch = getCurrentTouch ( touchStartPos . current . id , ev . touches ) ;
113
+
114
+ if ( ! touch ) {
115
+ return ;
116
+ }
117
+
118
+ const extraOffset = touch . clientX - touchStartPos . current . pos . x ;
119
+ setSpring ( { a : [ currentOffset . current + extraOffset ] } ) ;
120
+ } ;
121
+ const onTouchEnd = ( ev : TouchEvent ) => {
122
+ const touch = getCurrentTouch ( touchStartPos . current . id , ev . changedTouches ) ;
123
+
124
+ if ( ! touch ) {
125
+ return ;
126
+ }
127
+
128
+ const finalOffset = touch . clientX - touchStartPos . current . pos . x ;
129
+ setSpring ( { a : [ currentOffset . current + finalOffset ] } ) ;
130
+ currentOffset . current += finalOffset ;
131
+ touchStartPos . current . id = - 1 ;
132
+ } ;
133
+
134
+ // register touch events
135
+ useEffect ( ( ) => {
136
+ document . addEventListener ( "touchstart" , onTouchStart ) ;
137
+ document . addEventListener ( "touchmove" , onTouchMove ) ;
138
+ document . addEventListener ( "touchend" , onTouchEnd ) ;
139
+
140
+ return ( ) => {
141
+ document . removeEventListener ( "touchstart" , onTouchStart ) ;
142
+ document . removeEventListener ( "touchmove" , onTouchMove ) ;
143
+ document . removeEventListener ( "touchend" , onTouchEnd ) ;
144
+ } ;
145
+ } , [ ] ) ;
146
+
65
147
if ( ! enableGyro ) {
66
148
return < > { fallback } </ > ;
67
149
}
0 commit comments