Skip to content

Commit e8f0db1

Browse files
authored
Merge pull request #124 from 3DJakob/remove-react-panresponder-web
Remove react panresponder web
2 parents 47f660c + 723b3cb commit e8f0db1

File tree

2 files changed

+84
-53
lines changed

2 files changed

+84
-53
lines changed

index.js

+83-51
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const PanResponder = require('react-panresponder-web')
21
const React = require('react')
32
const { useSpring, animated } = require('@react-spring/web')
43

@@ -149,71 +148,104 @@ const TinderCard = React.forwardRef(
149148
)
150149

151150
let swipeThresholdFulfilledDirection = 'none'
152-
const panResponder = React.useMemo(
153-
() =>
154-
PanResponder.create({
155-
// Ask to be the responder:
156-
onStartShouldSetPanResponder: (evt, gestureState) => true,
157-
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
158-
onMoveShouldSetPanResponder: (evt, gestureState) => true,
159-
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
160-
161-
onPanResponderGrant: (evt, gestureState) => {
162-
// The gesture has started.
163-
// Probably wont need this anymore as postion i relative to swipe!
164-
setSpringTarget.start({ xyrot: [gestureState.dx, gestureState.dy, 0], config: physics.touchResponsive })
165-
},
166-
onPanResponderMove: (evt, gestureState) => {
167-
// Check fulfillment
168-
if (onSwipeRequirementFulfilled || onSwipeRequirementUnfulfilled) {
169-
const dir = getSwipeDirection({
170-
x: swipeRequirementType === 'velocity' ? gestureState.vx : gestureState.dx,
171-
y: swipeRequirementType === 'velocity' ? gestureState.vy : gestureState.dy
172-
})
173-
if (dir !== swipeThresholdFulfilledDirection) {
174-
swipeThresholdFulfilledDirection = dir
175-
if (swipeThresholdFulfilledDirection === 'none') {
176-
if (onSwipeRequirementUnfulfilled) onSwipeRequirementUnfulfilled()
177-
} else {
178-
if (onSwipeRequirementFulfilled) onSwipeRequirementFulfilled(dir)
179-
}
180-
}
181-
}
182151

183-
// use guestureState.vx / guestureState.vy for velocity calculations
184-
// translate element
185-
let rot = ((300 * gestureState.vx) / width) * 15// Magic number 300 different on different devices? Run on physical device!
186-
rot = Math.max(Math.min(rot, settings.maxTilt), -settings.maxTilt)
187-
setSpringTarget.start({ xyrot: [gestureState.dx, gestureState.dy, rot], config: physics.touchResponsive })
188-
},
189-
onPanResponderTerminationRequest: (evt, gestureState) => {
190-
return true
191-
},
192-
onPanResponderRelease: (evt, gestureState) => {
193-
// The user has released all touches while this view is the
194-
// responder. This typically means a gesture has succeeded
195-
// enable
196-
handleSwipeReleased(setSpringTarget, gestureState)
197-
}
198-
}),
199-
[]
200-
)
152+
const gestureStateFromWebEvent = (ev, startPositon, lastPosition, isTouch) => {
153+
let dx = isTouch ? ev.touches[0].clientX - startPositon.x : ev.clientX - startPositon.x
154+
let dy = isTouch ? ev.touches[0].clientY - startPositon.y : ev.clientY - startPositon.y
201155

202-
const element = React.useRef()
156+
// We cant calculate velocity from the first event
157+
if (startPositon.x === 0 && startPositon.y === 0) {
158+
dx = 0
159+
dy = 0
160+
}
161+
162+
const vx = -(dx - lastPosition.dx) / (lastPosition.timeStamp - Date.now())
163+
const vy = -(dy - lastPosition.dy) / (lastPosition.timeStamp - Date.now())
164+
165+
const gestureState = { dx, dy, vx, vy, timeStamp: Date.now() }
166+
return gestureState
167+
}
203168

204169
React.useLayoutEffect(() => {
170+
let startPositon = { x: 0, y: 0 }
171+
let lastPosition = { dx: 0, dy: 0, vx: 0, vy: 0, timeStamp: Date.now() }
172+
let isClicking = false
173+
205174
element.current.addEventListener(('touchstart'), (ev) => {
206175
if (!ev.srcElement.className.includes('pressable') && ev.cancelable) {
207176
ev.preventDefault()
208177
}
178+
179+
const gestureState = gestureStateFromWebEvent(ev, startPositon, lastPosition, true)
180+
lastPosition = gestureState
181+
startPositon = { x: ev.touches[0].clientX, y: ev.touches[0].clientY }
182+
})
183+
184+
element.current.addEventListener(('mousedown'), (ev) => {
185+
isClicking = true
186+
const gestureState = gestureStateFromWebEvent(ev, startPositon, lastPosition, false)
187+
lastPosition = gestureState
188+
startPositon = { x: ev.clientX, y: ev.clientY }
189+
})
190+
191+
const handleMove = (gestureState) => {
192+
// Check fulfillment
193+
if (onSwipeRequirementFulfilled || onSwipeRequirementUnfulfilled) {
194+
const dir = getSwipeDirection({
195+
x: swipeRequirementType === 'velocity' ? gestureState.vx : gestureState.dx,
196+
y: swipeRequirementType === 'velocity' ? gestureState.vy : gestureState.dy
197+
})
198+
if (dir !== swipeThresholdFulfilledDirection) {
199+
swipeThresholdFulfilledDirection = dir
200+
if (swipeThresholdFulfilledDirection === 'none') {
201+
if (onSwipeRequirementUnfulfilled) onSwipeRequirementUnfulfilled()
202+
} else {
203+
if (onSwipeRequirementFulfilled) onSwipeRequirementFulfilled(dir)
204+
}
205+
}
206+
}
207+
208+
// use guestureState.vx / guestureState.vy for velocity calculations
209+
// translate element
210+
let rot = gestureState.vx * 15 // Magic number 15 looks about right
211+
rot = Math.max(Math.min(rot, settings.maxTilt), -settings.maxTilt)
212+
setSpringTarget.start({ xyrot: [gestureState.dx, gestureState.dy, rot], config: physics.touchResponsive })
213+
}
214+
215+
window.addEventListener(('mousemove'), (ev) => {
216+
if (!isClicking) return
217+
const gestureState = gestureStateFromWebEvent(ev, startPositon, lastPosition, false)
218+
lastPosition = gestureState
219+
handleMove(gestureState)
220+
})
221+
222+
window.addEventListener(('mouseup'), (ev) => {
223+
if (!isClicking) return
224+
isClicking = false
225+
handleSwipeReleased(setSpringTarget, lastPosition)
226+
startPositon = { x: 0, y: 0 }
227+
lastPosition = { dx: 0, dy: 0, vx: 0, vy: 0, timeStamp: Date.now() }
228+
})
229+
230+
element.current.addEventListener(('touchmove'), (ev) => {
231+
const gestureState = gestureStateFromWebEvent(ev, startPositon, lastPosition, true)
232+
lastPosition = gestureState
233+
handleMove(gestureState)
234+
})
235+
236+
element.current.addEventListener(('touchend'), (ev) => {
237+
handleSwipeReleased(setSpringTarget, lastPosition)
238+
startPositon = { x: 0, y: 0 }
239+
lastPosition = { dx: 0, dy: 0, vx: 0, vy: 0, timeStamp: Date.now() }
209240
})
210241
})
211242

243+
const element = React.useRef()
244+
212245
return (
213246
React.createElement(AnimatedDiv, {
214247
ref: element,
215248
className,
216-
...panResponder.panHandlers,
217249
style: {
218250
transform: xyrot.to((x, y, rot) => `translate3d(${x}px, ${y}px, ${0}px) rotate(${rot}deg)`)
219251
},

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"test": "standard && ts-readme-generator --check"
1414
},
1515
"dependencies": {
16-
"p-sleep": "^1.1.0",
17-
"react-panresponder-web": "^1.0.2"
16+
"p-sleep": "^1.1.0"
1817
},
1918
"devDependencies": {
2019
"@types/react": "^16.9.51",

0 commit comments

Comments
 (0)