How to snap pictures using expo react native camera?

Arj*_*yap 7 react-native react-native-camera expo

I have just started using React Native with Expo so I am kind of confused. So, I have made a camera component which I imported in the main screen. Everything looks good. But I can't take pictures. I cannot click the snap icon and save the image. Is there a component that I missed? I have only posted the CameraComponent class below.

Camera.js

class CameraComponent extends Component {

  state = {
    hasCameraPermission: null,
    type: Camera.Constants.Type.back
  }

  async componentWillMount() {
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    this.setState({ hasCameraPermission: status === 'granted' })
  }

  render() {
    const { hasCameraPermission } = this.state

    if (hasCameraPermission === null) {
      return <View />
    }
    else if (hasCameraPermission === false) {
      return <Text> No access to camera</Text>
    }
    else {
      return (
        <View style={{ flex: 1 }}>
          <Camera 
            style={{ flex: 1, justifyContent: 'space-between' }}
            type={this.state.type}
          >
            <Header
              searchBar
              rounded
              style={{
                position: 'absolute',
                backgroundColor: 'transparent',
                left: 0,
                top: 0,
                right: 0,
                zIndex: 100,
                alignItems: 'center'
              }}
            >
              <View style={{ flexDirection: 'row', flex: 4 }}>
                <Ionicons name="md-camera" style={{ color: 'white' }} />
                <Item style={{ backgroundColor: 'transparent' }}>
                  <Icon name="ios-search" style={{ color: 'white', fontSize: 24, fontWeight: 'bold' }}></Icon>
                </Item>
              </View>

              <View style={{ flexDirection: 'row', flex: 2, justifyContent: 'space-around' }}>
                <Icon name="ios-flash" style={{ color: 'white', fontWeight: 'bold' }} />
                <Icon
                  onPress={() => {
                    this.setState({
                      type: this.state.type === Camera.Constants.Type.back ?                                        
                                            Camera.Constants.Type.front :
                                            Camera.Constants.Type.back
                    })
                  }}
                  name="ios-reverse-camera"
                  style={{ color: 'white', fontWeight: 'bold' }}
                />
              </View>
            </Header>

            <View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 30, marginBottom: 15, alignItems: 'flex-end' }}>
              <Ionicons name="ios-map" style={{ color: 'white', fontSize: 36 }}></Ionicons>
              <View></View>
              <View style={{ alignItems: 'center' }}>
                <MaterialCommunityIcons name="circle-outline"   // This is the icon which should take and save image
                  style={{ color: 'white', fontSize: 100 }}
                ></MaterialCommunityIcons>
                <Icon name="ios-images" style={{ color: 'white', fontSize: 36 }} />
              </View>
            </View>
          </Camera>
        </View>
      )
    }
  }
}

export default CameraComponent;
Run Code Online (Sandbox Code Playgroud)

The icon in the center i;e circle icon should automatically take and save image.

小智 8

您可以在异步 takePictureAsync 函数返回时使用“onPictureSaved”,以便您可以抓取照片对象:

  takePicture = () => {
      if (this.camera) {
          this.camera.takePictureAsync({ onPictureSaved: this.onPictureSaved });
      }
   };

  onPictureSaved = photo => {
      console.log(photo);
  } 
Run Code Online (Sandbox Code Playgroud)

在视图中,您将拥有一个带有 ref 的 Camera 组件:

<Camera style={styles.camera} type={this.state.type} ref={(ref) => { this.camera = ref }} >
Run Code Online (Sandbox Code Playgroud)

以及在按下时调用 takePicture 函数的按钮:

<TouchableOpacity style={styles.captureButton} onPress={this.takePicture} />
Run Code Online (Sandbox Code Playgroud)


Dir*_*ver 5

所以你需要告诉你的“圆圈图标”来拍照。首先我会像这样添加对你的相机的引用

<Camera style={{ flex: 1 }}
      ref={ (ref) => {this.camera = ref} }
      type={this.state.type}>
Run Code Online (Sandbox Code Playgroud)

然后创建一个实际告诉您的应用程序拍照的函数:

 async snapPhoto() {       
    console.log('Button Pressed');
    if (this.camera) {
       console.log('Taking photo');
       const options = { quality: 1, base64: true, fixOrientation: true, 
       exif: true};
       await this.camera.takePictureAsync(options).then(photo => {
          photo.exif.Orientation = 1;            
           console.log(photo);            
           });     
     }
    }
Run Code Online (Sandbox Code Playgroud)

现在让你的图标有一个 onPress() 来拍照。我做了这样的事情。

<TouchableOpacity style={styles.captureButton} onPress={this.snapPhoto.bind(this)}>
                <Image style={{width: 100, height: 100}} source={require('../assets/capture.png')}          
                />
            </TouchableOpacity>
Run Code Online (Sandbox Code Playgroud)

您可能还想创建一个呈现图像预览或类似内容的视图。Expo 文档有一个相当好的入门示例。请注意,Expo 会创建一个名为“Camera”的缓存文件夹,这就是图像最初所在的位置。

  • 有关此内容的文档位于:https://docs.expo.io/versions/latest/sdk/camera/ (2认同)

Eva*_*mez 5

您也可以在功能组件中使用通过 React Hook 创建的引用来执行此操作。这是基于 expo SDK 38 相机组件的示例https://docs.expo.io/versions/v38.0.0/sdk/camera/

import React, { useState, useEffect, useRef } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';

export default function App() {
  const [hasPermission, setHasPermission] = useState(null);
  const [type, setType] = useState(Camera.Constants.Type.back);
  const ref = useRef(null)

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestPermissionsAsync();
      setHasPermission(status === 'granted');
    })();
  }, []);
  
  _takePhoto = async () => {
    const photo = await ref.current.takePictureAsync()
    console.debug(photo)
  }

  if (hasPermission === null) {
    return <View />;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }
  return (
    <View style={{ flex: 1 }}>
      <Camera style={{ flex: 1 }} type={type} ref={ref}>
        <View
          style={{
            flex: 1,
            backgroundColor: 'transparent',
            flexDirection: 'row',
          }}>
          <TouchableOpacity
            style={{
              flex: 0.1,
              alignSelf: 'flex-end',
              alignItems: 'center',
            }}
            onPress={() => {
              setType(
                type === Camera.Constants.Type.back
                  ? Camera.Constants.Type.front
                  : Camera.Constants.Type.back
              );
            }}>
            <Text style={{ fontSize: 18, marginBottom: 10, color: 'white' }}> Flip </Text>
          </TouchableOpacity>
          <TouchableOpacity
            onPress={_takePhoto}
          >
            <Text>Snap Photo</Text>
          </TouchableOpacity>
        </View>
      </Camera>
    </View>
  );
}

Run Code Online (Sandbox Code Playgroud)

我没有检查 UI 的样子,但要点是利用React.useRef引用并将其附加到您的<Camera/>组件。然后您可以调用ref.current.takePictureAsync捕获并访问新图像。请参阅下文,了解拍摄照片的重要相关片段。

import React from 'react'
/* ... other imports
*/

export default CameraScene = () => {
  /* ... other state and permission logic
  */
  const ref = useRef(null)
  const _takePhoto = async () => {
    const photo = await ref.current.takePictureAsync()
    console.debug(photo)
  }
  return (
    <Camera style={{flex: 1}} ref={ref}> /* ...
    ... other ui logic
    */
    </Camera>
  ) 
}
Run Code Online (Sandbox Code Playgroud)

useRef在这里了解更多信息https://reactjs.org/docs/hooks-reference.html#useref