티스토리 뷰

개요

React Native를 이용하여 앱을 개발하려고 하는데, 만약 카메라가 필요하다면 어떻게 할까요? react-native-camera 라는 라이브러리를 이용해서 카메라 앱을 만드는 법을 알아보도록 하겠습니다.

프로젝트 만들기

react-native init cameraTest
cd cameraTest


react-native-camera 추가하기

npm install react-native-camera --save
react-native link react-native-camera

index 수정하기

Application이라는 컴포넌트로 구동하기 위해서 기본 소스를 수정하도록 하겠습니다.

import React from 'react';
import { AppRegistry } from 'react-native';

import Application from './src/Application';

AppRegistry.registerComponent('cameraTest', () => Application);


Application 컴포넌트 만들기

src라는 폴더 하위에 컴포넌트를 추가하겠습니다. Application.js를 만들어도 되고, Application 폴더를 생성한 뒤 내부에 index.js를 만들어도 됩니다. 처음은 View를 활용하여 컨테이너를 만들겠습니다.

import React, { Component } from 'react';
import { View } from 'react-native';

import styles from './styles';

export default class Application extends Component {
    constructor(props) {
        super();
    }
    render() {
        return (
            <View style={styles.container}>
            </View>
        );
    }
}

관련 스타일은 styles.js 파일을 생성하고 다음과 같이 만들겠습니다.

import React from 'react';
import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
});

export default styles;

StatusBar 감추기

카메라를 표출하려면 전체 화면으로 해야겠지요? 컨테이너 안에 <StatusBar>를 활용하여 상태바를 숨기도록 하겠습니다.

...
import { View, StatusBar } from 'react-native';
...
    render() {
        return (
            <View style={styles.container}>
                <StatusBar animated hidden />
            ...
        );
    }
}


카메라 표출하기

react-native-camera를 이용해서 표출하도록 하겠습니다. 추후에 촬영을 위해서 카메라 객체를 reference 하도록 하겠습니다.

...
import Camera from 'react-native-camera';
...
export default class Application extends Component {
    constructor(props) {
        super();
        this.camera = null;
    }
    ....
    render() {
        return (
            <View style={styles.container}>
                <StatusBar animated hidden />
                <Camera
                    ref={(cam) => {
                        this.camera = cam;
                    }}
                    style={styles.preview}
                />
            ....
        );
    }
}

카메라 미리보기 스타일은 styles.js에 추가하여 다음과 같이 하도록 하겠습니다.

....
    preview: {
        flex: 1,
        justifyContent: 'flex-end',
        alignItems: 'center',
    },
....


촬영버튼 표출하기

카메라의 미리보기까지 되었으면 촬영을 위하여 버튼을 추가 하겠습니다.
관련 버튼 이미지는 여기에서 다운받으시면 됩니다.

import React, { Component } from 'react';
import { View, StatusBar, TouchableOpacity, Image } from 'react-native';
...
import PhotoCaptureIcon from '../assets/ic_photo_camera_36pt.png';
...
    render() {
        return (
            <View style={styles.container}>
                <StatusBar animated hidden />
                <Camera
                    ref={(cam) => {
                        this.camera = cam;
                    }}
                    style={styles.preview}
                />
                <View style={[styles.overlay, styles.bottomOverlay]}>
                    <TouchableOpacity style={styles.captureButton}>
                        <Image source={PhotoCaptureIcon} />
                    </TouchableOpacity>
                </View>
            </View>
        );
    }
...

촬영버튼 스타일 또한 styles.js에 추가하겠습니다.

...
    overlay: {
        position: 'absolute',
        padding: 16,
        right: 0,
        left: 0,
        alignItems: 'center',
    },
    bottomOverlay: {
        bottom: 0,
        backgroundColor: 'rgba(0, 0, 0, 0.4)',
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
    },
    captureButton: {
        padding: 15,
        backgroundColor: 'white',
        borderRadius: 40,
    },
...

촬영 이벤트 만들기

버튼까지 만들었으면 촬영을 하는 이벤트를 추가하겠습니다. TouchableOpacity의 onPress 이벤트를 활용하겠습니다.

Camera 객체의 capture를 호출하면 사진 촬영을 할 수 있습니다.

...
    takePicture = () => {
        if(this.camera) {
            this.camera.capture()
            .then((data) => console.log(data))
            .catch(err => console.error(err));
        }
    }
...
      <View style={[styles.overlay, styles.bottomOverlay]}>
        <TouchableOpacity style={styles.captureButton} onPress={this.takePicture}>
          <Image source={PhotoCaptureIcon} />
        </TouchableOpacity>
      </View>
...


전체 소스

작성된 Application.js 와 styles.js 는 다음과 같습니다.

import React, { Component } from 'react';
import { View, StatusBar, TouchableOpacity, Image } from 'react-native';
import Camera from 'react-native-camera';

import styles from './styles';

import PhotoCaptureIcon from '../assets/ic_photo_camera_36pt.png';

export default class Application extends Component {
    constructor(props) {
        super();
        this.camera = null;
    }
    takePicture = () => {
        if(this.camera) {
            this.camera.capture()
            .then((data) => console.log(data))
            .catch(err => console.error(err));
        }
    }
    render() {
        return (
            <View style={styles.container}>
                <StatusBar animated hidden />
                <Camera
                    ref={(cam) => {
                        this.camera = cam;
                    }}
                    style={styles.preview}
                />
                <View style={[styles.overlay, styles.bottomOverlay]}>
                    <TouchableOpacity style={styles.captureButton} onPress={this.takePicture}>
                        <Image source={PhotoCaptureIcon} />
                    </TouchableOpacity>
                </View>
            </View>
        );
    }
}

import React from 'react';
import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    preview: {
        flex: 1,
        justifyContent: 'flex-end',
        alignItems: 'center',
    },
    overlay: {
        position: 'absolute',
        padding: 16,
        right: 0,
        left: 0,
        alignItems: 'center',
    },
    bottomOverlay: {
        bottom: 0,
        backgroundColor: 'rgba(0, 0, 0, 0.4)',
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
    },
    captureButton: {
        padding: 15,
        backgroundColor: 'white',
        borderRadius: 40,
    },
});

export default styles;


참고 내용


댓글
댓글쓰기 폼