yarn add react-native-reanimated
...const SIZE = 100.0;export default function App() {return (<GestureHandlerRootView style={{flex: 1}}><View style={styles.container}><View style={styles.square} /></View></GestureHandlerRootView>);}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#fff',alignItems: 'center',justifyContent: 'center',},square: {width: SIZE,height: SIZE,backgroundColor: 'rgba(0,0,255,0.5)',borderRadius: 20 // just for fun :)}});
import Animated from 'react-native-reanimated'import { PanGestureHandler } from 'react-native-gesture-handler'const SIZE = 100.0export default function App() {return (<GestureHandlerRootView style={{flex: 1}}><View style={styles.container}><PanGestureHandler><Animated.View style={styles.square} /></PanGestureHandler><View style={styles.container}></GestureHandlerRootView>);}
<PanGestureHandler onGestureEvent={🧐🧐🧐}>...</PanGestureHandler>
import Animated, { useAnimatedGestureHandler } from 'react-native-reanimated'...export default function App() {const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({onStart: () => {},onActive: (event) => {console.log(event.translationX)},onEnd: () => {},});return (<GestureHandlerRootView style={{flex: 1}}><View style={styles.container}><PanGestureHandler onGestureEvent={panGestureEvent}><Animated.View style={styles.square} /></PanGestureHandler><View style={styles.container}></GestureHandlerRootView>);}
...export default function App() {// 1.const translateX = useSharedValue(0)const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({onStart: () => {},onActive: (event) => {// 2.translateX.value = event.translationX},onEnd: () => {},});// 3.const rStyle = useAnimatedStyle(() => {return {transform: [{translateX: translateX.value,},],};});return (<GestureHandlerRootView style={{flex: 1}}><View style={styles.container}><PanGestureHandler onGestureEvent={panGestureEvent}><Animated.View style={[styles.square, rStyle]} /> {/* 4. */}</PanGestureHandler><View style={styles.container}></GestureHandlerRootView>);}
...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({onStart: (_, context) => {},onActive: (event, context) => {translateX.value = event.translationX},onEnd: () => {},});...
...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({onStart: (_, context) => {context.translateX = translateX.value // 1.},onActive: (event, context) => {translateX.value = event.translationX + context.translateX // 2.},onEnd: () => {},});...
const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,🦄🦄🦄>({...})
type ContextType = {translateX: number;};export default function App() {...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({...})...}...
...type ContextType = {translateX: number;translateY: number;};export default function App() {const translateX = useSharedValue(0)const translateY = useSharedValue(0)const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({onStart: () => {context.translateX = translateX.valuecontext.translateY = translateY.value},onActive: (event) => {translateX.value = event.translationX + context.translateXtranslateY.value = event.translationY + context.translateY},onEnd: () => {},});const rStyle = useAnimatedStyle(() => {return {transform: [{translateX: translateX.value,},{translateY: translateY.value,},],};});return (<GestureHandlerRootView style={{flex: 1}}><View style={styles.container}><PanGestureHandler onGestureEvent={panGestureEvent}><Animated.View style={[styles.square, rStyle]} /></PanGestureHandler><View style={styles.container}></GestureHandlerRootView>);}
...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({onStart: () => {context.translateX = translateX.valuecontext.translateY = translateY.value},onActive: (event) => {translateX.value = event.translationX + context.translateXtranslateY.value = event.translationY + context.translateY},onEnd: () => {translateX.value = 0translateY.value = 0},});...
...import { withSpring } from 'react-native-reanimated'...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({onStart: () => {context.translateX = translateX.valuecontext.translateY = translateY.value},onActive: (event) => {translateX.value = event.translationX + context.translateXtranslateY.value = event.translationY + context.translateY},onEnd: () => {translateX.value = withSpring(0)translateY.value = withSpring(0)},});...
return (<GestureHandlerRootView style={{ flex: 1 }}><View style={styles.container}><View style={styles.circle}><PanGestureHandler onGestureEvent={panGestureEvent}><Animated.View style={[styles.square, rStyle]} /></PanGestureHandler></View></View></GestureHandlerRootView>);
const CIRCLE_RADIUS = SIZE * 2;const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#fff',alignItems: 'center',justifyContent: 'center',},square: {width: SIZE,height: SIZE,backgroundColor: 'rgba(0, 0, 255, 0.5)',borderRadius: 20,},circle: {width: CIRCLE_RADIUS * 2,height: CIRCLE_RADIUS * 2,alignItems: 'center',justifyContent: 'center',borderRadius: CIRCLE_RADIUS,borderWidth: 5,borderColor: 'rgba(0, 0, 255, 0.5)',},});
...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({onStart: () => {context.translateX = translateX.valuecontext.translateY = translateY.value},onActive: (event) => {translateX.value = event.translationX + context.translateXtranslateY.value = event.translationY + context.translateY},onEnd: () => {const distance = Math.sqrt(translateX.value ** 2 + translateY.value ** 2);if (distance < CIRCLE_RADIUS) {translateX.value = withSpring(0);translateY.value = withSpring(0);}},});...
...const panGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent,ContextType>({onStart: () => {context.translateX = translateX.valuecontext.translateY = translateY.value},onActive: (event) => {translateX.value = event.translationX + context.translateXtranslateY.value = event.translationY + context.translateY},onEnd: () => {const distance = Math.sqrt(translateX.value ** 2 + translateY.value ** 2);if (distance < CIRCLE_RADIUS + SIZE / 2) {translateX.value = withSpring(0);translateY.value = withSpring(0);}},});...
Every week I send out a newsletter sharing new things about React Native animations.