-
-
Save SGarcia710/c7364aea14b401e37c29768a415a02e5 to your computer and use it in GitHub Desktop.
react-native-gesture-handler + react-native-reanimate example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useMemo, useRef } from 'react'; | |
import { View } from 'react-native'; | |
import { node } from 'prop-types'; | |
import { PanGestureHandler, State, PinchGestureHandler } from 'react-native-gesture-handler'; | |
import Animated from 'react-native-reanimated'; | |
import styles from './styles'; | |
/** styles.js | |
import { StyleSheet } from 'react-native'; | |
export default StyleSheet.create({ | |
container: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
backgroundColor: '#F5FCFF', | |
}, | |
box: { | |
width: 50, | |
height: 50, | |
margin: 20, | |
backgroundColor: 'red', | |
}, | |
}); | |
*/ | |
const { add, set, block, cond, eq, multiply, max, concat } = Animated; | |
const usePan = () => { | |
const offsetX = useRef(new Animated.Value(0)).current; | |
const offsetY = useRef(new Animated.Value(0)).current; | |
const transX = useRef(new Animated.Value(0)).current; | |
const transY = useRef(new Animated.Value(0)).current; | |
const handlePan = useMemo(() => { | |
return Animated.event([ | |
{ | |
nativeEvent: ({ translationX: x, translationY: y, state }) => | |
block([ | |
set(transX, add(offsetX, x)), | |
set(transY, add(offsetY, y)), | |
cond(eq(state, State.END), [ | |
set(offsetX, add(offsetX, x)), | |
set(offsetY, add(offsetY, y)), | |
]), | |
]), | |
}, | |
]); | |
}, [offsetX, offsetY, transX, transY]); | |
return { offsetX, offsetY, transX, transY, handlePan }; | |
}; | |
const PanView = ({ children, ...props }) => { | |
const { transX, transY, handlePan } = usePan(); | |
return ( | |
<PanGestureHandler onGestureEvent={handlePan} onHandlerStateChange={handlePan} {...props}> | |
<Animated.View style={{ transform: [{ translateX: transX, translateY: transY }] }}> | |
{children} | |
</Animated.View> | |
</PanGestureHandler> | |
); | |
}; | |
PanView.propTypes = { | |
children: node, | |
}; | |
const usePinch = () => { | |
const zoom = useRef(new Animated.Value(1)).current; | |
const offset = useRef(new Animated.Value(1)).current; | |
const handlePinch = useMemo(() => { | |
return Animated.event([ | |
{ | |
nativeEvent: ({ scale, state }) => | |
block([ | |
cond(eq(state, State.ACTIVE), set(zoom, max(multiply(offset, scale), 1))), | |
cond(eq(state, State.END), [set(offset, max(multiply(offset, scale), 1))]), | |
]), | |
}, | |
]); | |
}, [offset, zoom]); | |
return { scale: zoom, offset, handlePinch }; | |
}; | |
const PinchView = ({ children, ...props }) => { | |
const { scale: zoom, handlePinch } = usePinch(); | |
return ( | |
<PinchGestureHandler onGestureEvent={handlePinch} onHandlerStateChange={handlePinch} {...props}> | |
<Animated.View style={{ transform: [{ scale: zoom }] }}>{children}</Animated.View> | |
</PinchGestureHandler> | |
); | |
}; | |
PinchView.propTypes = { | |
children: node, | |
}; | |
const useRotate = () => { | |
const rotationValue = useRef(new Animated.Value(0)).current; | |
const offset = useRef(new Animated.Value(0)).current; | |
const handleRotate = useMemo(() => { | |
return Animated.event([ | |
{ | |
nativeEvent: ({ rotation, state }) => | |
block([ | |
set(rotationValue, add(rotation, offset)), | |
cond(eq(state, State.END), [set(offset, add(rotation, offset))]), | |
]), | |
}, | |
]); | |
}, [offset, rotationValue]); | |
return { rotation: rotationValue, offset, handleRotate }; | |
}; | |
const RotateView = ({ children, ...props }) => { | |
const { rotation, handleRotate } = useRotate(); | |
return ( | |
<RotationGestureHandler | |
onGestureEvent={handleRotate} | |
onHandlerStateChange={handleRotate} | |
{...props}> | |
<Animated.View style={{ transform: [{ rotate: concat(rotation, 'rad') }] }}> | |
{children} | |
</Animated.View> | |
</RotationGestureHandler> | |
); | |
}; | |
PinchView.propTypes = { | |
children: node, | |
}; | |
const Sandbox = () => { | |
const panRef = useRef(); | |
const pinchRef = useRef(); | |
const rotateRef = useRef(); | |
return ( | |
<View style={styles.container}> | |
<PanView ref={panRef} simultaneousHandlers={[pinchRef, rotateRef]}> | |
<PinchView ref={pinchRef} simultaneousHandlers={[panRef, rotateRef]}> | |
<RotateView ref={rotateRef} simultaneousHandlers={[pinchRef, panRef]}> | |
<View style={styles.box} /> | |
</RotateView> | |
</PinchView> | |
</PanView> | |
</View> | |
); | |
}; | |
export default Sandbox; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment