Search code examples
iosreactjsreact-nativereact-reduxreact-native-gesture-handler

Implement pinch zoom using one touch react native


I want to achieve the pinch gesture (zoom) using single Touch of finger in the react native. ![Having four arrow at side of the images. Need to implement the pinch zoom using single touch][1]

https://i.sstatic.net/ykqSb.png


Solution

  • You can use react-native-gesture-handler to implement this. I simply write some code. Firstly longly press the corner will show the indicator to drag, then drag will change the scale of the image. I don't complete all the functions but just show you some logic. Maybe you should complete by yourself!

    https://snack.expo.io/@gwl002/onetouchzoom

    A expo snack for the same code

    
    import { StatusBar } from 'expo-status-bar';
    import React, { useState, useRef } from 'react';
    import { StyleSheet, Text, View, Image, Alert, Animated } from 'react-native';
    import 'react-native-gesture-handler';
    import { TapGestureHandler, PanGestureHandler, LongPressGestureHandler, State } from 'react-native-gesture-handler';
    
    export default function App() {
      const [dirButton, setDirButton] = useState(null);
      const imgLongPress = useRef();
      const imgPan = useRef();
      const scaleAnim = new Animated.Value(1);
    
      return (
        <View style={styles.container}>
          <StatusBar style="auto" />
          <LongPressGestureHandler
            ref={imgLongPress}
            simultaneousHandlers={imgPan}
            onHandlerStateChange={({ nativeEvent }) => {
              if (nativeEvent.state === State.ACTIVE) {
                let { x, y } = nativeEvent;
                let buttonPosition = "";
                console.log(x, y);
                if (x < 30 && y < 30) {
                  buttonPosition = "topLeft";
                } else if (x > 370 && y < 30) {
                  buttonPosition = "topRight";
                } else if (x < 30 && y > 370) {
                  buttonPosition = "bottomLeft";
                } else if (x > 370 && y > 370) {
                  buttonPosition = "bottomRight";
                } else {
                  buttonPosition = null
                }
                setDirButton(buttonPosition)
              }
            }}
            minDurationMs={800}
          >
            <PanGestureHandler
              ref={imgPan}
              simultaneousHandlers={imgLongPress}
              onGestureEvent={({ nativeEvent }) => {
                if (dirButton) {
                  console.log(nativeEvent)
                  let { x, y } = nativeEvent;
                  if (dirButton === "topRight" || dirButton === "bottomRight") {
                    scaleAnim.setValue(x / 400)
                  } else if (dirButton === "topLeft" || dirButton === "bottomLeft") {
                    scaleAnim.setValue((400 - x) / 400)
                  }
                }
              }}
            >
              <View style={styles.wrapper}>
                <Animated.Image
                  source={require("./assets/test.png")}
                  style={[
                    { width: 400, height: 400 },
                    {
                      transform: [
                        { scale: scaleAnim }
                      ]
                    }
                  ]}
                />
                <View
                  style={[styles.indicator, dirButton ? styles[dirButton] : { width: 0, height: 0 }]}
                >
    
                </View>
              </View>
            </PanGestureHandler>
          </LongPressGestureHandler>
    
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        paddingTop: 100,
        backgroundColor: '#fff',
      },
      wrapper: {
        position: "relative",
      },
      indicator: {
        width: 30,
        height: 30,
        backgroundColor: "blue",
        position: "absolute"
      },
      topLeft: {
        left: 0,
        top: 0
      },
      topRight: {
        right: 0,
        top: 0
      },
      bottomLeft: {
        left: 0,
        bottom: 0,
      },
      bottomRight: {
        right: 0,
        bottom: 0
      }
    });
    
    

    long press the left top corner and then drag to zoom