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

如何在react-native-vision-camera中从自定义框区域捕获图像?

如何在react-native-vision-camera中从自定义框区域捕获图像?

我来帮你解决这个问题,在react-native-vision-camera里实现自定义区域图像捕获,核心思路是先渲染可调整的选择框,捕获全图后再裁剪对应区域——因为VisionCamera本身没有直接指定捕获区域的API,不过我们可以通过坐标转换+图像裁剪来实现,下面是具体步骤:


1. 在相机预览上叠加自定义选择框

首先,你需要在Camera组件上方渲染一个可交互的矩形框(这里先写基础固定框,你可以扩展成可拖动/调整大小的组件),同时记录框的屏幕坐标和尺寸。

import { Camera, useCameraDevices } from 'react-native-vision-camera';
import { View, TouchableOpacity, StyleSheet, Text } from 'react-native';
import { useState, useRef } from 'react';

export default function CustomCaptureScreen() {
  const devices = useCameraDevices();
  const backCamera = devices.back;
  const cameraRef = useRef(null);
  // 存储自定义框的屏幕坐标(x,y)和宽高
  const [cropArea, setCropArea] = useState({
    x: 100,
    y: 200,
    width: 300,
    height: 300,
  });

  if (!backCamera) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>找不到相机设备</Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      {/* 相机预览 */}
      <Camera
        ref={cameraRef}
        style={styles.camera}
        device={backCamera}
        isActive={true}
      />
      {/* 自定义选择框 - 可扩展为可拖动/调整大小的交互组件 */}
      <View
        style={[
          styles.cropFrame,
          {
            left: cropArea.x,
            top: cropArea.y,
            width: cropArea.width,
            height: cropArea.height,
          },
        ]}
      />
      {/* 捕获按钮 */}
      <TouchableOpacity style={styles.captureBtn} onPress={handleCapture}>
        <View style={styles.btnInner} />
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
  cropFrame: {
    position: 'absolute',
    borderWidth: 2,
    borderColor: '#fff',
    backgroundColor: 'rgba(0,0,0,0.3)', // 半透明遮罩突出选择区域
  },
  captureBtn: {
    position: 'absolute',
    bottom: 30,
    alignSelf: 'center',
    width: 70,
    height: 70,
    borderRadius: 35,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
  },
  btnInner: {
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#ff4444',
  },
});

2. 转换屏幕坐标到图像真实坐标

相机捕获的图像分辨率和屏幕预览的分辨率通常不一致,所以需要把屏幕上的选择框坐标转换成图像的真实坐标,这样裁剪才会准确。

const handleCapture = async () => {
  if (!cameraRef.current) return;

  // 1. 捕获全尺寸图像
  const fullPhoto = await cameraRef.current.takePhoto({
    qualityPrioritization: 'speed', // 优先速度,也可以选'quality'
  });

  // 2. 获取相机的传感器分辨率和预览显示尺寸
  const sensorRes = backCamera.sensorResolution;
  const previewSize = await cameraRef.current.getCameraPreviewSize();

  // 3. 计算屏幕到图像的缩放比例
  const scaleX = sensorRes.width / previewSize.width;
  const scaleY = sensorRes.height / previewSize.height;

  // 4. 转换选择框坐标到图像坐标(部分设备传感器是横屏,需额外调整方向,这里先处理基础情况)
  const imageCropArea = {
    originX: cropArea.x * scaleX,
    originY: cropArea.y * scaleY,
    width: cropArea.width * scaleX,
    height: cropArea.height * scaleY,
  };

  // 5. 调用裁剪函数处理图像
  await cropCapturedImage(fullPhoto.path, imageCropArea);
};

3. 裁剪捕获的图像

可以用expo-image-manipulator(Expo项目)或者react-native-image-crop-picker(纯RN项目)实现图像裁剪,这里以Expo的库为例:

import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';

const cropCapturedImage = async (imagePath, cropArea) => {
  try {
    const croppedImage = await manipulateAsync(
      imagePath,
      [
        {
          crop: cropArea, // 传入转换后的图像裁剪区域
        },
      ],
      { compress: 0.8, format: SaveFormat.JPEG } // 压缩比例和格式
    );

    // 这里可以处理裁剪后的图像:比如显示到Image组件、保存到相册等
    console.log('裁剪后的图像路径:', croppedImage.uri);
  } catch (error) {
    console.error('裁剪失败:', error);
  }
};

额外注意事项

  • 相机方向适配:部分安卓设备的相机传感器是横屏的,捕获的图像可能会旋转,这时候需要在裁剪前先旋转图像(可以在manipulateAsync里添加rotate操作)。
  • 权限处理:确保已经申请了相机权限和存储权限(安卓),可以用react-native-permissions来处理。
  • 选择框交互优化:如果需要用户自由拖动或调整选择框大小,可以结合react-native-gesture-handler和react-native-reanimated实现流畅交互。

备注:内容来源于stack exchange,提问作者hgq287

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:13:12