You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用React Native Vision Camera与Gesture Handler实现点击聚焦异常求助

React Native Vision Camera 点击聚焦失效问题修复

问题描述

在React Native应用中,使用React Native Vision Camera结合react-native-gesture-handler实现相机点击聚焦功能时出现异常:有时点击位置变模糊,有时完全无反应。虽然能正常打印点击的x、y坐标,但相机并未聚焦到对应点。

原代码片段

const handleFocusOnTap = async(tapEvent) => {
    try {
        if (cameraDevice.supportsFocus && cameraRef && tapEvent && tapEvent.x !== undefined && tapEvent.y !== undefined) {
            
            await cameraRef?.current?.focus({
                    x: tapEvent.x,
                    y: tapEvent.y
            });
            console.log(tapEvent.x, tapEvent.y)    
        }
    } catch (e) {
        console.error(e);            
    }
};

const tap = Gesture.Tap().onEnd((event, success) => {
    const focusAsync = async() => {
        await handleFocusOnTap(event);
    };
    if (success) {          
        focusAsync();
    } else {
        console.error()
    }
});

return (
    <>
        <StatusBar style="light"/>
        <AfterInteractions>
            <View style={cameraScreenStyles.cameraContainer}>
                <GestureDetector gesture={tap} >
                    <Camera
                        style={cameraScreenStyles.camera}
                        ref={cameraRef}
                        device={cameraDevice}
                        isActive={true}
                        photo={true}
                        enableZoomGesture={true}
                        enableHighQualityPhotos={true}
                        orientation={orientation}
                        focusable={true}
                    />
                </GestureDetector>
...

修复方案

1. 转换为归一化坐标

Vision Camera的focus方法要求传入0-1之间的归一化坐标,而react-native-gesture-handler返回的是组件内的像素坐标,需要进行转换:

  • 首先获取Camera组件的实际宽高:
import { useState, useRef } from 'react';

const cameraViewRef = useRef(null);
const [cameraSize, setCameraSize] = useState({ width: 0, height: 0 });

// 在Camera组件上添加onLayout事件
<Camera
  ref={cameraRef}
  onLayout={(e) => {
    const { width, height } = e.nativeEvent.layout;
    setCameraSize({ width, height });
  }}
  // 其他原有props...
/>
  • 修改handleFocusOnTap方法,转换坐标:
const handleFocusOnTap = async(tapEvent) => {
    try {
        if (cameraDevice.supportsFocus && cameraRef.current && tapEvent && cameraSize.width > 0 && cameraSize.height > 0) {
            // 转换为归一化坐标
            const normalizedX = tapEvent.x / cameraSize.width;
            const normalizedY = tapEvent.y / cameraSize.height;
            
            await cameraRef.current.focus({
                x: normalizedX,
                y: normalizedY
            });
        }
    } catch (e) {
        console.error('聚焦失败:', e);            
    }
};

2. 简化异步手势处理

去掉嵌套的async函数,直接在手势onEnd中异步调用聚焦方法,避免异步上下文丢失:

const tap = Gesture.Tap().onEnd(async (event, success) => {
    if (success) {          
        await handleFocusOnTap(event);
    } else {
        console.error('手势识别失败');
    }
});

3. 验证设备支持与权限

  • 确认cameraDevice.supportsFocus返回true,可以在控制台打印该值进行验证;
  • 检查相机权限是否完全授予,Android需确保CAMERA权限已申请,iOS需在Info.plist中添加NSCameraUsageDescription。

4. 升级Vision Camera版本

如果使用的是旧版本,尝试升级到最新稳定版,部分聚焦API的bug已在新版本中修复。


内容的提问来源于stack exchange,提问作者Joanna Philips

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:52:45