React Native 中如何使用手机摄像头拍照并获取数据
Posted
技术标签:
【中文标题】React Native 中如何使用手机摄像头拍照并获取数据【英文标题】:How to take a picture and get the data in React Native with the mobile camera 【发布时间】:2018-08-25 18:24:19 【问题描述】:在你说这是重复之前,让我解释一下。 我知道如何在 React Native 中使用 Camera,但是上个月在 android(Java) 中我以一种简单的方式管理设备摄像头,我什至不必创建一个新的 View 来使用它。我只是做了这样的事情:
Uri mOutputFileUri;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri); // URI of the file where pic will be stored
startActivityForResult(intent, TAKE_PICTURE_FROM_CAMERA);
基本上这会自动打开相机,当按下“拍照按钮”时,会调用 onActivityForResult() 方法,获取要管理的图像数据。
所以,我的疑问是,有没有办法在 React Native 中做到这一点?我的意思是,调用一个自动打开相机并返回数据的方法?
非常感谢。
【问题讨论】:
【参考方案1】:最简单的方法是使用 ImagePicker 库https://github.com/react-community/react-native-image-picker
这允许您打开本机相机并使用照片中的数据获取提供的回调。
ImagePicker.launchCamera(options, (response) =>
// Response data
);
【讨论】:
【参考方案2】:您还可以使用 expo-camera 和 expo-av(用于视频)。这是一个快速原型,它还管理设备权限。
import React, useState, useRef, useEffect from "react";
import
StyleSheet,
Dimensions,
View,
Text,
TouchableOpacity,
SafeAreaView,
from "react-native";
import Camera from "expo-camera";
import Video from "expo-av";
const WINDOW_HEIGHT = Dimensions.get("window").height;
const closeButtonSize = Math.floor(WINDOW_HEIGHT * 0.032);
const captureSize = Math.floor(WINDOW_HEIGHT * 0.09);
export default function App()
const [hasPermission, setHasPermission] = useState(null);
const [cameraType, setCameraType] = useState(Camera.Constants.Type.back);
const [isPreview, setIsPreview] = useState(false);
const [isCameraReady, setIsCameraReady] = useState(false);
const [isVideoRecording, setIsVideoRecording] = useState(false);
const [videoSource, setVideoSource] = useState(null);
const cameraRef = useRef();
useEffect(() =>
(async () =>
const status = await Camera.requestPermissionsAsync();
setHasPermission(status === "granted");
)();
, []);
const onCameraReady = () =>
setIsCameraReady(true);
;
const takePicture = async () =>
if (cameraRef.current)
const options = quality: 0.5, base64: true, skipProcessing: true ;
const data = await cameraRef.current.takePictureAsync(options);
const source = data.uri;
if (source)
await cameraRef.current.pausePreview();
setIsPreview(true);
console.log("picture source", source);
;
const recordVideo = async () =>
if (cameraRef.current)
try
const videoRecordPromise = cameraRef.current.recordAsync();
if (videoRecordPromise)
setIsVideoRecording(true);
const data = await videoRecordPromise;
const source = data.uri;
if (source)
setIsPreview(true);
console.log("video source", source);
setVideoSource(source);
catch (error)
console.warn(error);
;
const stopVideoRecording = () =>
if (cameraRef.current)
setIsPreview(false);
setIsVideoRecording(false);
cameraRef.current.stopRecording();
;
const switchCamera = () =>
if (isPreview)
return;
setCameraType((prevCameraType) =>
prevCameraType === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
;
const cancelPreview = async () =>
await cameraRef.current.resumePreview();
setIsPreview(false);
setVideoSource(null);
;
const renderCancelPreviewButton = () => (
<TouchableOpacity onPress=cancelPreview style=styles.closeButton>
<View style=[styles.closeCross, transform: [ rotate: "45deg" ] ] />
<View
style=[styles.closeCross, transform: [ rotate: "-45deg" ] ]
/>
</TouchableOpacity>
);
const renderVideoPlayer = () => (
<Video
source= uri: videoSource
shouldPlay=true
style=styles.media
/>
);
const renderVideoRecordIndicator = () => (
<View style=styles.recordIndicatorContainer>
<View style=styles.recordDot />
<Text style=styles.recordTitle>"Recording..."</Text>
</View>
);
const renderCaptureControl = () => (
<View style=styles.control>
<TouchableOpacity disabled=!isCameraReady onPress=switchCamera>
<Text style=styles.text>"Flip"</Text>
</TouchableOpacity>
<TouchableOpacity
activeOpacity=0.7
disabled=!isCameraReady
onLongPress=recordVideo
onPressOut=stopVideoRecording
onPress=takePicture
style=styles.capture
/>
</View>
);
if (hasPermission === null)
return <View />;
if (hasPermission === false)
return <Text style=styles.text>No access to camera</Text>;
return (
<SafeAreaView style=styles.container>
<Camera
ref=cameraRef
style=styles.container
type=cameraType
flashMode=Camera.Constants.FlashMode.on
onCameraReady=onCameraReady
onMountError=(error) =>
console.log("cammera error", error);
/>
<View style=styles.container>
isVideoRecording && renderVideoRecordIndicator()
videoSource && renderVideoPlayer()
isPreview && renderCancelPreviewButton()
!videoSource && !isPreview && renderCaptureControl()
</View>
</SafeAreaView>
);
const styles = StyleSheet.create(
container:
...StyleSheet.absoluteFillObject,
,
closeButton:
position: "absolute",
top: 35,
left: 15,
height: closeButtonSize,
width: closeButtonSize,
borderRadius: Math.floor(closeButtonSize / 2),
justifyContent: "center",
alignItems: "center",
backgroundColor: "#c4c5c4",
opacity: 0.7,
zIndex: 2,
,
media:
...StyleSheet.absoluteFillObject,
,
closeCross:
width: "68%",
height: 1,
backgroundColor: "black",
,
control:
position: "absolute",
flexDirection: "row",
bottom: 38,
width: "100%",
alignItems: "center",
justifyContent: "center",
,
capture:
backgroundColor: "#f5f6f5",
borderRadius: 5,
height: captureSize,
width: captureSize,
borderRadius: Math.floor(captureSize / 2),
marginHorizontal: 31,
,
recordIndicatorContainer:
flexDirection: "row",
position: "absolute",
top: 25,
alignSelf: "center",
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent",
opacity: 0.7,
,
recordTitle:
fontSize: 14,
color: "#ffffff",
textAlign: "center",
,
recordDot:
borderRadius: 3,
height: 6,
width: 6,
backgroundColor: "#ff0000",
marginHorizontal: 5,
,
text:
color: "#fff",
,
);
来源 - Instamobile
【讨论】:
以上是关于React Native 中如何使用手机摄像头拍照并获取数据的主要内容,如果未能解决你的问题,请参考以下文章
React Native开发之expo中camera的基本使用
React Native - 使用库 react-native-camera 调用摄像头扫描二维码以及条形码