@@ -10,12 +10,25 @@ export interface Interaction {
10
10
// Check if an event was triggered by touch
11
11
const isTouch = ( event : MouseEvent | TouchEvent ) : event is TouchEvent => "touches" in event ;
12
12
13
+ const getPoint = ( touches : TouchList , touchId : null | number ) : Touch => {
14
+ for ( let i = 0 ; i < touches . length ; i ++ ) {
15
+ if ( touches [ i ] . identifier === touchId ) {
16
+ return touches [ i ] ;
17
+ }
18
+ }
19
+ return touches [ 0 ] ;
20
+ } ;
21
+
13
22
// Returns a relative position of the pointer inside the node's bounding box
14
- const getRelativePosition = ( node : HTMLDivElement , event : MouseEvent | TouchEvent ) : Interaction => {
23
+ const getRelativePosition = (
24
+ node : HTMLDivElement ,
25
+ event : MouseEvent | TouchEvent ,
26
+ touchId : null | number
27
+ ) : Interaction => {
15
28
const rect = node . getBoundingClientRect ( ) ;
16
29
17
30
// Get user's pointer position from `touches` array if it's a `TouchEvent`
18
- const pointer = isTouch ( event ) ? event . touches [ 0 ] : ( event as MouseEvent ) ;
31
+ const pointer = isTouch ( event ) ? getPoint ( event . touches , touchId ) : ( event as MouseEvent ) ;
19
32
20
33
return {
21
34
left : clamp ( ( pointer . pageX - ( rect . left + window . pageXOffset ) ) / rect . width ) ,
@@ -46,6 +59,7 @@ const InteractiveBase = ({ onMove, onKey, ...rest }: Props) => {
46
59
const container = useRef < HTMLDivElement > ( null ) ;
47
60
const onMoveCallback = useEventCallback < Interaction > ( onMove ) ;
48
61
const onKeyCallback = useEventCallback < Interaction > ( onKey ) ;
62
+ const touchId = useRef < null | number > ( null ) ;
49
63
const hasTouch = useRef ( false ) ;
50
64
51
65
const [ handleMoveStart , handleKeyDown , toggleDocumentEvents ] = useMemo ( ( ) => {
@@ -57,12 +71,15 @@ const InteractiveBase = ({ onMove, onKey, ...rest }: Props) => {
57
71
preventDefaultMove ( nativeEvent ) ;
58
72
59
73
if ( isInvalid ( nativeEvent , hasTouch . current ) || ! el ) return ;
60
- hasTouch . current = isTouch ( nativeEvent ) ;
74
+ if ( isTouch ( nativeEvent ) ) {
75
+ hasTouch . current = true ;
76
+ touchId . current = nativeEvent . changedTouches [ 0 ] . identifier ;
77
+ }
61
78
62
79
// The node/ref must actually exist when user start an interaction.
63
80
// We won't suppress the ESLint warning though, as it should probably be something to be aware of.
64
81
el . focus ( ) ;
65
- onMoveCallback ( getRelativePosition ( el , nativeEvent ) ) ;
82
+ onMoveCallback ( getRelativePosition ( el , nativeEvent , touchId . current ) ) ;
66
83
toggleDocumentEvents ( true ) ;
67
84
} ;
68
85
@@ -78,7 +95,7 @@ const InteractiveBase = ({ onMove, onKey, ...rest }: Props) => {
78
95
const isDown = isTouch ( event ) ? event . touches . length > 0 : event . buttons > 0 ;
79
96
80
97
if ( isDown && container . current ) {
81
- onMoveCallback ( getRelativePosition ( container . current , event ) ) ;
98
+ onMoveCallback ( getRelativePosition ( container . current , event , touchId . current ) ) ;
82
99
} else {
83
100
toggleDocumentEvents ( false ) ;
84
101
}
0 commit comments