Skip to content

Instantly share code, notes, and snippets.

@mcousillas6
Last active August 9, 2023 07:38
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mcousillas6/1a4864cd6c008bed8fb0450726d8a191 to your computer and use it in GitHub Desktop.
Save mcousillas6/1a4864cd6c008bed8fb0450726d8a191 to your computer and use it in GitHub Desktop.
react-native-gesture-handler + react-native-reanimate example
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;
@cawfree
Copy link

cawfree commented Apr 13, 2021

This is very useful, thanks for sharing! Minor enhancement; I believe for simultaneousHandlers to work you need to forwardRef your functional components. 🙏

@fatihkayan20
Copy link

Pich is not working please help me ? I need to use pichGesture and panGesture

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment