Easily add pinch and zoom gestures to your React Native components.
npm install --save react-native-pinch-zoom-responder
import React, {
Component
} from 'react'
import {
View,
Text
} from 'react-native'
import MatrixMath from 'react-native/Libraries/Utilities/MatrixMath'
import PinchZoomResponder from 'react-native-pinch-zoom-responder'
class MyComponent extends Component {
constructor (props) {
super(props)
this.state = {
width: 1,
height: 1
}
this.pinchZoomResponder = new PinchZoomResponder({
onPinchZoomStart: (e) => {
console.log('pinch started')
},
onPinchZoomEnd: (e) => {
console.log('pinch ended')
},
onResponderMove: (e, gestureState) => {
if (gestureState) {
console.log('GestureState is ', gestureState)
var transform = this._applyOriginTransform(gestureState.transform)
this._setTransform(transform)
}
}
})
}
_onLayout (event) {
this.setState({
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height
})
}
_setTransform (matrix) {
this.transformView.setNativeProps({ style: { transform: [{perspective: 1000}, { matrix: matrix }] } })
}
/*
React Native view transforms have the component center as their origin,
so we need to wrap our transform with translations that compensate for this and
place the origin at 0,0
*/
_applyOriginTransform (matrix) {
var translate = MatrixMath.createIdentityMatrix()
var copy = matrix.slice()
MatrixMath.reuseTranslate2dCommand(translate, (this.state.width / 2.0), (this.state.height / 2.0))
MatrixMath.multiplyInto(copy, matrix, translate)
MatrixMath.reuseTranslate2dCommand(translate, -(this.state.width / 2.0), -(this.state.height / 2.0))
MatrixMath.multiplyInto(copy, translate, copy)
return copy
}
render () {
return (
<View {...this.pinchZoomResponder.handlers} onLayout={(e) => this._onLayout(e)}>
<Text ref={(ref) => { this.transformView = ref }}>Pinch me!</Text>
<View
style={{position: 'absolute', left: 0, top: 0, bottom: 0, right: 0}}
height='100%'
width='100%' />
</View>
)
}
}
NOTICE the absolutely positioned view! This is a hack to ensure the event's locationX coordinates are not transformed.
The gestureState object has the shape:
{
transform, cx, cy, scaleX, scaleY, dx, dy
}
transform
is a 4x4 matrix that can be used withreact-native/Libraries/Utilities/MatrixMath
to easily transform points and graphics.cx
is the pinch X centercy
is the pinch Y centerscaleX
is the pinch x scalescaleY
is the pinch y scaledx
is the current delta x of the center of the pinchdy
is the current delta y of the center of the pinch
The responder can also receive a set of options as the second parameter.
var responders = {
onPinchZoomStart: (e) => {}
onPinchZoomEnd: (e) => {}
onResponderMove: (e, gestureState) => {}
}
var options = {
transformX: true,
transformY: true
}
new PinchZoomResponder(responders, options)
The options
object is optional and it's fields can include:
transformX
true | false. True by default. Enables transformation along the X axistransformY
true | false. True by default. Enables transformation along the Y axis.