使用react-native-camera拍照

时间:2020-05-01

文档:https://www.npmjs.com/package/react-native-camera

安装(仅针对安卓手机)

npm install react-native-camera --save

react-native link react-native-camera

添加权限(android\app\src\main\AndroidManifest.xml)

<uses-permission android:name="android.permission.CAMERA" />

修改 android\app\build.gradle

missingDimensionStrategy 'react-native-camera', 'general'

以上就安装完成了。

开始使用

使用拍照组件

<RNCamera
	ref={ref => {
		this.camera = ref;
	}}
	style={styles.preview}
	type={RNCamera.Constants.Type.back}
	flashMode={RNCamera.Constants.FlashMode.off}
	androidCameraPermissionOptions={{
		title: '相机权限',
		message: '本功能需要相机权限才可以使用哦',
		buttonPositive: '确定',
	}}
	notAuthorizedView={notAuthorizedView}
	onStatusChange={this.onStatusChange}
/>

属性值参考:https://react-native-community.github.io/react-native-camera/docs/api

onStatusChange方法,这个方法可以判断是否打开了相机权限

/**
	* 相机权限变化
	* @param cameraStatus
*/
onStatusChange = ({cameraStatus}) => {
	if (cameraStatus === 'NOT_AUTHORIZED') {
		this.setState({
			camera: false,
		});
	}
};

拍照方法

/**
     * 拍照
     * @returns {Promise<void>}
     */
    takePicture = async () => {
        if (this.camera) {
            const options = {quality: 0.5, base64: false};
            const data = await this.camera.takePictureAsync(options);
            // 暂停预览
            this.camera.pausePreview();
            this.setState({
                uri: data.uri,
                canTakePhoto: false,
            });
        }
    };

完整代码

import React, {PureComponent} from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
import styles from '../Styles';
import {RNCamera} from 'react-native-camera';

export default class PhotoScreen extends PureComponent {
    constructor(props) {
        super(props);
    }

    state = {
        camera: true,//有没有拍照权限
        uri: '',//拍照图片路径
        canTakePhoto: true,//是否可以拍照
    };

    componentDidMount(): void {
        let title = '';
        switch (this.props.route.params.type) {
            case 1:
                title = '拍照搜题';
                break;
        }
        // 修改标题栏文字
        this.props.navigation.setOptions({
            title,
        });
    }

    /**
     * 相机权限变化
     * @param cameraStatus
     */
    onStatusChange = ({cameraStatus}) => {
        if (cameraStatus === 'NOT_AUTHORIZED') {
            this.setState({
                camera: false,
            });
        }
    };

    /**
     * 拍照
     * @returns {Promise<void>}
     */
    takePicture = async () => {
        if (this.camera) {
            const options = {quality: 0.5, base64: false};
            const data = await this.camera.takePictureAsync(options);
            // 暂停预览
            this.camera.pausePreview();
            this.setState({
                uri: data.uri,
                canTakePhoto: false,
            });
        }
    };

    // 取消搜索
    cancelSearch = () => {
        if (this.camera) {
            // 暂停预览
            this.camera.resumePreview();
            this.setState({
                canTakePhoto: true,
            });
        }
    };

    // 去搜索
    toSearch = () => {
        console.log(this.state.uri);
    };

    render(): React.ReactNode {
        const notAuthorizedView = (<View style={styles.notAuthorizedView}>
            <Text style={styles.warnColor}>请开启相机权限</Text>
        </View>);

        let takePhotoTextView = null;
        if (this.state.camera) {
            if (this.state.canTakePhoto) {
                // 显示拍照按钮
                takePhotoTextView = (<View style={styles.photoText}>
                    <TouchableOpacity
                        style={[styles.flex0, styles.warnBtn]}
                        onPress={this.takePicture.bind(this)}
                    >
                        <Text style={styles.warnColor}>拍照</Text>
                    </TouchableOpacity>
                </View>);
            } else {
                takePhotoTextView = (<View style={styles.photoText}>
                    <TouchableOpacity
                        style={[styles.flex0, styles.warnBtn]}
                        onPress={this.cancelSearch.bind(this)}
                    >
                        <Text style={styles.warnColor}>取消</Text>
                    </TouchableOpacity>
                    <TouchableOpacity
                        style={[styles.flex0, styles.ml15, styles.primaryBtn]}
                        onPress={this.toSearch.bind(this)}
                    >
                        <Text style={styles.whiteColor}>确定</Text>
                    </TouchableOpacity>
                </View>);
            }
        }
        return (<View style={styles.takePhoto}>
            <RNCamera
                ref={ref => {
                    this.camera = ref;
                }}
                style={styles.preview}
                type={RNCamera.Constants.Type.back}
                flashMode={RNCamera.Constants.FlashMode.off}
                androidCameraPermissionOptions={{
                    title: '相机权限',
                    message: '本功能需要相机权限才可以使用哦',
                    buttonPositive: '确定',
                }}
                notAuthorizedView={notAuthorizedView}
                onStatusChange={this.onStatusChange}
            />
            {takePhotoTextView}
        </View>);
    }
}

官网给出的示例

'use strict';
import React, { PureComponent } from 'react';
import { AppRegistry, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { RNCamera } from 'react-native-camera';

class ExampleApp extends PureComponent {
  render() {
    return (
      <View style={styles.container}>
        <RNCamera
          ref={ref => {
            this.camera = ref;
          }}
          style={styles.preview}
          type={RNCamera.Constants.Type.back}
          flashMode={RNCamera.Constants.FlashMode.on}
          androidCameraPermissionOptions={{
            title: 'Permission to use camera',
            message: 'We need your permission to use your camera',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
          androidRecordAudioPermissionOptions={{
            title: 'Permission to use audio recording',
            message: 'We need your permission to use your audio',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
          onGoogleVisionBarcodesDetected={({ barcodes }) => {
            console.log(barcodes);
          }}
        />
        <View style={{ flex: 0, flexDirection: 'row', justifyContent: 'center' }}>
          <TouchableOpacity onPress={this.takePicture.bind(this)} style={styles.capture}>
            <Text style={{ fontSize: 14 }}> SNAP </Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }

  takePicture = async () => {
    if (this.camera) {
      const options = { quality: 0.5, base64: true };
      const data = await this.camera.takePictureAsync(options);
      console.log(data.uri);
    }
  };
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    backgroundColor: 'black',
  },
  preview: {
    flex: 1,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  capture: {
    flex: 0,
    backgroundColor: '#fff',
    borderRadius: 5,
    padding: 15,
    paddingHorizontal: 20,
    alignSelf: 'center',
    margin: 20,
  },
});

AppRegistry.registerComponent('App', () => ExampleApp);