How to implement tap on focus in react natie using expo camera?

2.5k Views Asked by At

I am using expo camera and I have wrapped it inside TapGestureHandler so I can detect tap event. Here is the code:

<TapGestureHandler onHandlerStateChange={onSingleTapEvent}>
  <View>
    <Camera
      ref={cameraRef}
      type={cameraType}
      ratio={ratio}
      onCameraReady={onCameraReady}
      autoFocus={Camera.Constants.AutoFocus.on}
    ></Camera>
  </View>
</TapGestureHandler>;

My onSingleTapEvent:

 const onSingleTapEvent = (event) => {
    if (event.nativeEvent.state === State.ACTIVE) {
      console.log("Single tap event: ", event.nativeEvent);
    }
  };

When I tap on the screen I see the following console output:

    Single tap event:  Object {
  "absoluteX": 210.3333282470703,
  "absoluteY": 527.3333129882812,
  "handlerTag": 3,
  "numberOfPointers": 1,
  "oldState": 2,
  "state": 4,
  "x": 210.3333282470703,
  "y": 446.3333435058594,
}

My question is, how do I implement tap on focus? As far as I understand I need to play with focusDepth property of expo camera, but I don't know how to set it? Any ideas, bogs or pseudo code would be grant!

1

There are 1 best solutions below

2
On

I've found a nice way to do this by resetting the autofocus on user tap event and it works really well.

export default function CameraScreen({ route, navigation }: any) {
    const [isRefreshing, setIsRefreshing] = useState(false);
    const [focusSquare, setFocusSquare] = useState({ visible: false, x: 0, y: 0 });

    useEffect(() => {
        if (isRefreshing) {
            setIsRefreshing(false);
        }
    }, [isRefreshing]);

    // Function to handle touch events
    const handleTouch = (event: any) => {
        const { locationX, locationY } = event.nativeEvent;
        setFocusSquare({ visible: true, x: locationX, y: locationY });

        // Hide the square after 1 second
        setTimeout(() => {
            setFocusSquare((prevState) => ({ ...prevState, visible: false }));
        }, 1000);

        setIsRefreshing(true);
    };

    return (
    <GestureHandlerRootView style={{flex: 1}}>
        <PinchGestureHandler
          onGestureEvent={handlePinch}
          onHandlerStateChange={(event) => {
            if (event.nativeEvent.state === State.END) {
              const scale = event.nativeEvent.scale;
              setZoom((currentZoom) => scale * currentZoom);
            }
          }}
        >
          <View style={styles.container}>
            <Camera
              style={styles.camera}
              type={type}
              ref={camera}
              zoom={zoom}
              autoFocus={!isRefreshing ? AutoFocus.on : AutoFocus.off}
              onTouchEnd={handleTouch} // Handle touch to set focus point
            >
            </Camera>

            {focusSquare.visible && (
              <View
                style={[
                  styles.focusSquare,
                  { top: focusSquare.y - 25, left: focusSquare.x - 25 },
                ]}
              />
            )}

          </View>
        </PinchGestureHandler>
      </GestureHandlerRootView>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
    },
    camera: {
        flex: 1,
    },
    focusSquare: {
        position: 'absolute',
        width: 50,
        height: 50,
        borderWidth: 2,
        borderColor: 'white',
        backgroundColor: 'transparent',
    },
});