forked from wonday/react-native-pdf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PinchZoomView.js
89 lines (76 loc) · 3.28 KB
/
PinchZoomView.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
'use strict'
import React, { useRef } from 'react'
import PropTypes from 'prop-types'
import { View, StyleSheet, PanResponder } from 'react-native'
import { ViewPropTypes } from 'deprecated-react-native-prop-types'
const PinchZoomView = (props) => {
const distant = useRef(0)
const gestureHandlers = useRef(
PanResponder.create({
onStartShouldSetPanResponder: handleStartShouldSetPanResponder,
onMoveShouldSetResponderCapture: (e, gestureState) => true,
onMoveShouldSetPanResponder: handleMoveShouldSetPanResponder,
onPanResponderGrant: handlePanResponderGrant,
onPanResponderMove: handlePanResponderMove,
onPanResponderRelease: handlePanResponderEnd,
onPanResponderTerminationRequest: (e) => false,
onPanResponderTerminate: handlePanResponderTerminate,
onShouldBlockNativeResponder: (e) => true
})
).current
const handleStartShouldSetPanResponder = (e, gestureState) => {
// don't respond to single touch to avoid shielding click on child components
return false
}
const handleMoveShouldSetPanResponder = (e, gestureState) => {
return props?.scalable && (e.nativeEvent.changedTouches.length >= 2 || gestureState.numberActiveTouches >= 2)
}
const handlePanResponderGrant = (e, gestureState) => {
if (e.nativeEvent.changedTouches.length >= 2 || gestureState.numberActiveTouches >= 2) {
let dx = Math.abs(e.nativeEvent.touches[0].pageX - e.nativeEvent.touches[1].pageX)
let dy = Math.abs(e.nativeEvent.touches[0].pageY - e.nativeEvent.touches[1].pageY)
distant.current = Math.sqrt(dx * dx + dy * dy)
}
}
const handlePanResponderEnd = (e, gestureState) => {
distant.current = 0
}
const handlePanResponderTerminate = (e, gestureState) => {
distant.current = 0
}
const handlePanResponderMove = (e, gestureState) => {
if ((e.nativeEvent.changedTouches.length >= 2 || gestureState.numberActiveTouches >= 2) && distant?.current > 100) {
let dx = Math.abs(e.nativeEvent.touches[0].pageX - e.nativeEvent.touches[1].pageX)
let dy = Math.abs(e.nativeEvent.touches[0].pageY - e.nativeEvent.touches[1].pageY)
let distant = Math.sqrt(dx * dx + dy * dy)
let scale = distant / distant?.current
let pageX = (e.nativeEvent.touches[0].pageX + e.nativeEvent.touches[1].pageX) / 2
let pageY = (e.nativeEvent.touches[0].pageY + e.nativeEvent.touches[1].pageY) / 2
let pinchInfo = { scale: scale, pageX: pageX, pageY: pageY }
props?.onScaleChanged(pinchInfo)
distant.current = distant
}
}
PinchZoomView.propTypes = {
...ViewPropTypes,
scalable: PropTypes.bool,
onScaleChanged: PropTypes.func
}
PinchZoomView.defaultProps = {
scalable: true,
onScaleChanged: (scale) => {}
}
return (
<View {...props} {...gestureHandlers?.panHandlers} style={[styles.container, props?.style]}>
{props?.children}
</View>
)
}
export default PinchZoomView
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})