ExpoとReactNativeを使用してカメラアプリを作成する方法

Expoに慣れていない場合は、ビルドの複雑さを軽減してReactNativeアプリをビルドするのに役立つクライアントです。また、ReactNativeを実行するための環境のインストールとセットアップのストレスに対処するのにも役立ちます。

このチュートリアルでは、ユーザーが写真を撮ったり、写真のプレビューを表示したり、フラッシュモードを使用したり、前面カメラと背面カメラを切り替えたりできる簡単なカメラアプリを作成します。

前提条件

Expoは、最初のReactNativeアプリの構築を開始するのにそれほど多くのことを必要としません。expoとexpo-cliのインストールについて詳しくは、こちらのドキュメントをご覧ください。

注:このチュートリアルでは、macOSとiOSを使用します。Androidも使用できますが、現時点では万博を使用しても大きな違いはありません。

次のコマンドを実行して、expoとexpo-cliをグローバルにインストールできます。

npm install --global expo-cli

Expoを実行するにはNodejsが必要です。こちらの公式サイトで最新バージョンを実行できます。

入門

ExpoとNodejsをインストールした後、次のコマンドを使用して新しいExpoプロジェクトのブートストラップを開始できます。

expo init expo-camera-app

パッケージをインストールしてアプリを実行する方法

Expoは、作成中のアプリのプレビューを実行および表示できるクライアントアプリを提供します。AppStoreとGooglePlayの両方でダウンロードできます。

これはアプリのインターフェースです。

エキスポプロジェクトを開始する方法

アプリディレクトリに移動し、アプリを実行します。

cd expo-camera-app 

アプリのデフォルトテンプレートを選択するためのいくつかの質問が表示されます。このチュートリアルでは、空白(TypeScript)オプションを選択するだけですが、ここでも、自分に合ったものを自由に選択できます。

アプリを実行する

プロジェクトをブートストラップした後、次のコマンドでアプリを実行できます expo run

これにより、ログを表示できるウィンドウがブラウザに開きます。また、スキャンしてデバイスでアプリを実行できるQRコードも生成されます。

Expoの良いところは、アプリを実行するためにシミュレーターをインストールして構成する必要がないことです。シミュレーターでexpoを実行するオプションは引き続き提供されますが、シミュレーターを自分でインストールして構成する必要があります。

アプリに戻ります。デバイスでアプリを正常に実行したとすると、これがデフォルトの画面になります。

お気に入りのコードエディタでアプリディレクトリを開きます。私はVSCodeを使用しています。

は次のApp.tsxようになります。

import {StatusBar} from 'expo-status-bar' import React from 'react' import {StyleSheet, Text, View} from 'react-native' export default function App() { return (  Open up App.tsx to start working on your app!   ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } }) 

UIの作成方法

プロジェクトを実行した後、UIの作成を開始します。

expo-cameraをインストールする

次のステップは、次のようにexpo-cameraをインストールすることです。

expo install expo-camera

We will create a simple UI that will allow the user to start the process of using the camera.

import {StatusBar} from 'expo-status-bar' import React from 'react' import {StyleSheet, Text, View, TouchableOpacity} from 'react-native' export default function App() { return (     Take picture      ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } }) 

It's a simple UI: we import TouchableOpacity for the button and do some simple styling. If you are wondering how styling works in React Native, you can check out my two articles here:

  • Styling in React Native
  • Demystifying Flexbox in React Native

Now we have to use a useState hook to manage the state and display the camera view when the user press the take picture button.

   Take picture  
 const [startCamera,setStartCamera] = React.useState(false) const __startCamera = ()=>{ }

There are two important things we have to do when the user presses the button:

  • Ask permission to access the camera. In mobile development, accessing many native APIs and mobile features is often restricted by the user's permissions and the privacy. It's just something that you have to get used to when developing mobile apps.
  • Change the state and present the camera.

Let's import the camera module from expo-camera with this command:

import {Camera} from 'expo-camera'

And add the camera view, like this:

  { camera = r }} >

We can use ref to access the camera's methods:

let camera: Camera

When the take picture button is pressed the __startCamera function will be called:

 const __startCamera = async () => { const {status} = await Camera.requestPermissionsAsync() if(status === 'granted'){ // do something }else{ Alert.alert("Access denied") }

The function will ask for permission first. If the user grant access to the camera, we can proceed and open the camera. If not, we show a simple alert.

Add the camera component

Let's display the camera when the user grants access to the device's camera.

 const __startCamera = async () => { const {status} = await Camera.requestPermissionsAsync() if (status === 'granted') { // start the camera setStartCamera(true) } else { Alert.alert('Access denied') } }

We have to make some changes to the UI and add a conditional rendering. We display the camera only when the user requests it, otherwise we display the default screen.

 {startCamera ? (  { camera = r }} > ) : (    Take picture    )}

Cool, now we need to add a button so we can take the actual picture.

Add the capture button

This is a simple View inside the camera view that has an absolute position. So we make sure that it is always on the top of the camera.

How to take a picture

The app should take a picture when capture button is pressed. That function will look like the below:

 const __takePicture = async () => { if (!camera) return const photo = await camera.takePictureAsync() }

First, we check that we have access to the Camera component using ref:

 if (!camera) return // if the camera is undefined or null, we stop the function execution

Then we take the picture by calling the takePictureAsync method. It returns a promise and an object that contains the picture's details. The result will look like this:

Object { "height": 4224, "uri": "file:///var/mobile/Containers/Data/Application/E6740A15-93AF-4120-BF11-6E8B74AFBF93/Library/Caches/ExponentExperienceData/%2540anonymous%252Fcamera-app-ee0fa3c8-1bb1-4d62-9863-33bf26341c55/Camera/19F0C5DD-7CA6-4043-8D89-AF65A1055C7E.jpg", "width": 1952, }

We are only interested in the Picture URL uri. After we take a picture, we have to show the photo preview and hide the camera view. To do that we will use two hooks to change the state:

 const [previewVisible, setPreviewVisible] = useState(false) const [capturedImage, setCapturedImage] = useState(null)
 const __takePicture = async () => { if (!camera) return const photo = await camera.takePictureAsync() console.log(photo) setPreviewVisible(true) setCapturedImage(photo) }
  • setPreviewVisible to show the preview
  • setCapturedImage(photo) to store the object result

Then we display the preview like this:

 {previewVisible && capturedImage ? (  ) : (  { camera = r }} >         )}

The CameraPreview component looks like this:

const CameraPreview = ({photo}: any) => { console.log('sdsfds', photo) return (    ) }

And the result looks like this:

How to re-take a picture

We can add some buttons to the preview that will allow the user to perform more actions. For example, they could re-take the photo or save it.

Add the savePhoto and retakePicture props to the CameraPreview component like this:

When the Re-take button is pressed, we will have to hide the preview, remove the current picture, and show the camera again. Do that with the following code:

 const __retakePicture = () => { setCapturedImage(null) setPreviewVisible(false) __startCamera() }

How to add other options – back camera, flash, and more

expo-camra offers many options for customizing the camera, like FlashMode, setting the Camera type (front/back), zooming, and so on.

How to add FlashMode

Let's add an option so the user can turn FlashMode on and off:

We simply create a small button to switch off/on the flash, like this:

   ⚡️  

And we just change the state when the button is pressed:

 const [flashMode, setFlashMode] = React.useState('off') const __handleFlashMode = () => { if (flashMode === 'on') { setFlashMode('off') } else if (flashMode === 'off') { setFlashMode('on') } else { setFlashMode('auto') } }

And then we add FlashMode props:

  { camera = r }} >

How to access the front and the back camera

We will add a button that switches between the back and front camera.

We can get the default camera type directly from the camera module like below:

 const [cameraType, setCameraType] = React.useState(Camera.Constants.Type.back)

Add type props like this:

  { camera = r }} >

And add the switch button:

  {cameraType === 'front' ? '?' : '?'}  

And switch function:

 const __switchCamera = () => { if (cameraType === 'back') { setCameraType('front') } else { setCameraType('back') } }

Here is the result:

You can find the full source code on GitHub.

Wrapping up

In general, Expo is an amazing tool that can save you a lot of time. It helps you start building directly and saves you the pain of environment setup.

ネイティブ拡張機能を構築し、独自の方法でネイティブ機能を使用して処理したい場合があります。この場合、ネイティブコードを簡単に変更して操作できるように、react-nativeCLIを使用することをお勧めします。

こんにちは、私の名前はサイードハヤニです。私はsubscribi.ioを作成して、クリエイター、ブロガー、インフルエンサーがニュースレターを通じて視聴者を増やすのを支援しました。

React Nativeの詳細に興味がある場合は、私のメーリングリストに参加してください。