React Native 入門してみた④  カメラ実装編

[React Native 入門してみた③ Httpアクセス編 - Qiita](https://qiita.com/garbanzo/items/a2bb2cdb0f65273ed84d)につづいて今回はカメラ実装についての入門です。

# カメラ実装
カメラ機能の実装も何かに使うかも？ということで試してみました。
ExpoにCameraのAPIが用意されているので、そちらを使用して実装してみます。
[Camera- Expo Documentation](https://docs.expo.io/versions/v32.0.0/sdk/camera/)に使用サンプルがあるので、サンプルを元に実装します。
 
### 実装

#### ファイル構成

```
├── App.tsx
├── app.json
├── assets
├── babel.config.js
├── package-lock.json
├── package.json
└── tsconfig.json
```
こちらも前回同様のTypeScript構成です。
ここではデフォルトのまま特に追加せず、`App.tsx`のみ編集します。


とりあえず、上記リンクにある`Basic Example`の実装をコピペ

#### App.tsx

```
import React from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera, Permissions } from 'expo';

export default class CameraExample extends React.Component {
  state = {
    hasCameraPermission: null,
    type: Camera.Constants.Type.back,
  };

  async componentDidMount() {
    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 }} type={this.state.type}>
            <View
              style={{
                flex: 1,
                backgroundColor: 'transparent',
                flexDirection: 'row',
              }}>
              <TouchableOpacity
                style={{
                  flex: 0.1,
                  alignSelf: 'flex-end',
                  alignItems: 'center',
                }}
                onPress={() => {
                  this.setState({
                    type: this.state.type === Camera.Constants.Type.back
                      ? Camera.Constants.Type.front
                      : Camera.Constants.Type.back,
                  });
                }}>
                <Text
                  style={{ fontSize: 18, marginBottom: 10, color: 'white' }}>
                  {' '}Flip{' '}
                </Text>
              </TouchableOpacity>
            </View>
          </Camera>
        </View>
      );
    }
  }
}
```
カメラを起動するには実機が必要です。
iOSに[Expoアプリ]()をインストールして、iPhoneのカメラでQRコード読み取り起動します。(Expo起動時に表示されるQRコードです。)

起動するとカメラの起動ができます。
上記コードではカメラの起動のみなので、さらに写真を取って保存する処理を実装してみます。
App.tsxを編集します。

```
...
  private camera?: CameraObject;

  constructor(props: {}) {
    super(props);
  }

...
  async takePicture() {
    if (this.camera) {
      const pictureData = await this.camera!.takePictureAsync();
      CameraRoll.saveToCameraRoll(pictureData.uri);
    }
  }
...

```
まずは、写真を保存する処理を追加します。
`CameraObject`の`takePictureAsync`で画像データを取得します。
`CameraRoll`の`saveToCameraRoll`に先程取得して画面データのurlを指定して保存します。

つづいて`render`の修正です。

```

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 }} type={this.state.type}
            ref={(ref: any) => {
              this.camera = ref;
            }}
          >
            <View
              style={{
                flex: 1,
                backgroundColor: 'transparent',
                flexDirection: 'row',
              }}>
              <TouchableOpacity
                style={{
                  flex: 0.1,
                  alignSelf: 'flex-end',
                  alignItems: 'center',
                }}
                onPress={() => {
                  this.setState({
                    type: this.state.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
+               style={{
+                 flex: 1,
+                 alignSelf: 'flex-end',
+                 alignItems: 'center',
+               }}
+               onPress={() => this.takePicture()}>
+               <Text
+                 style={{ fontSize: 18, marginBottom: 10, color: 'white' }}>
+                 {' '}Camera{' '}
+               </Text>
+             </TouchableOpacity>
            </View>
          </Camera>
        </View>
      );
    }
  }
```
CameraコンポーネントにTouchableOpacityコンポーネントを追加します。
`onPress`に先程作成して`takePicutre`関数を指定します。
これで画面下部に`Camera`という文字が表示されタップすることで写真を保存出来るようになりました。
とても簡単に実装出来ますね。 

## Next
続いては、[React Native 入門してみた⑤ データ永続化編 - Qiita](https://qiita.com/garbanzo/items/f10c08a0888e84f3af4f)です。