Cách tạo ứng dụng máy ảnh với Expo và React Native

Nếu bạn không quen với triển lãm, thì đó là một ứng dụng khách giúp bạn xây dựng các ứng dụng React Native với ít phức tạp hơn trong việc xây dựng. Nó cũng giúp bạn giải quyết những căng thẳng khi cài đặt và thiết lập môi trường để chạy React Native.

Trong hướng dẫn này, chúng tôi sẽ xây dựng một ứng dụng máy ảnh đơn giản, trong đó người dùng có thể chụp ảnh, xem trước ảnh của họ, sử dụng chế độ đèn flash và chuyển đổi giữa máy ảnh trước và sau.

Điều kiện tiên quyết

Expo không yêu cầu nhiều để bắt đầu xây dựng ứng dụng React Native đầu tiên của bạn. Bạn có thể tìm hiểu thêm về cách cài đặt expo và expo-cli tại đây trong tài liệu.

Lưu ý: trong hướng dẫn này, tôi sẽ sử dụng macOS và iOS. Bạn cũng có thể sử dụng Android, không có nhiều khác biệt khi sử dụng expo vào thời điểm này.

Bạn có thể cài đặt expo và expo-cli trên toàn cầu bằng cách chạy lệnh sau:

npm install --global expo-cli

Expo yêu cầu Nodejs để chạy. Bạn có thể chạy phiên bản mới nhất trên trang web chính thức tại đây.

Bắt đầu

Sau khi bạn đã cài đặt Expo và Nodejs, bạn có thể bắt đầu khởi động một dự án Expo mới bằng lệnh bên dưới:

expo init expo-camera-app

Cách cài đặt các gói và chạy ứng dụng

Expo cung cấp cho chúng tôi một ứng dụng khách để chúng tôi có thể chạy và xem bản xem trước của ứng dụng mà chúng tôi đang xây dựng. Nó có sẵn trên cả App Store và Google Play để tải xuống.

Đây là giao diện của ứng dụng.

Cách bắt đầu một dự án triển lãm

Truy cập thư mục ứng dụng và chạy ứng dụng.

cd expo-camera-app 

Bạn sẽ được hỏi một số câu hỏi để chọn mẫu mặc định cho ứng dụng. Trong hướng dẫn này, chúng tôi chỉ cần chọn một tùy chọn trống (TypeScript), nhưng một lần nữa, bạn có thể tự do chọn những gì phù hợp với mình.

Chạy ứng dụng

Sau khi khởi động dự án, chúng tôi có thể chạy ứng dụng với expo run

Thao tác này sẽ mở ra một cửa sổ trong trình duyệt của bạn, nơi bạn có thể xem nhật ký. Nó cũng sẽ tạo mã QR mà bạn có thể quét để chạy ứng dụng trên thiết bị của mình.

Điều tốt về triển lãm là bạn không cần cài đặt và định cấu hình trình mô phỏng để chạy ứng dụng. Nó vẫn cung cấp cho bạn tùy chọn để chạy triển lãm trên trình mô phỏng, nhưng bạn phải tự cài đặt và định cấu hình trình mô phỏng.

Quay lại ứng dụng của chúng tôi. Giả sử bạn đã chạy thành công ứng dụng trên thiết bị, đây sẽ là màn hình mặc định:

Mở thư mục ứng dụng trong trình soạn thảo mã yêu thích của bạn. Tôi đang sử dụng VS Code.

Di App.tsxchúc trông như thế này:

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' } }) 

Cách tạo giao diện người dùng

Sau khi dự án chạy, bây giờ là lúc bắt đầu tạo một số giao diện người dùng.

Cài đặt camera hội chợ

Bước tiếp theo là cài đặt camera hội chợ, như sau:

expo install expo-camera

Chúng tôi sẽ tạo một giao diện người dùng đơn giản cho phép người dùng bắt đầu quá trình sử dụng máy ảnh.

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' } }) 

Đó là một giao diện người dùng đơn giản: chúng tôi nhập TouchableOpacitycho nút và thực hiện một số kiểu đơn giản. Nếu bạn đang thắc mắc về cách tạo kiểu hoạt động trong React Native, bạn có thể xem hai bài viết của tôi tại đây:

  • Tạo kiểu trong React Native
  • Làm sáng tỏ Flexbox trong React Native

Bây giờ chúng ta phải sử dụng useStatehook để quản lý trạng thái và hiển thị chế độ xem camera khi người dùng nhấn nút chụp ảnh .

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

Có hai điều quan trọng chúng ta phải làm khi người dùng nhấn nút:

  • Yêu cầu quyền truy cập máy ảnh. Trong phát triển di động, việc truy cập nhiều API gốc và các tính năng di động thường bị hạn chế bởi quyền của người dùng và quyền riêng tư. Nó chỉ là thứ mà bạn phải làm quen khi phát triển ứng dụng di động.
  • 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.

Đôi khi bạn có thể muốn tạo một tiện ích mở rộng gốc và xử lý bằng cách sử dụng các tính năng gốc theo cách của riêng bạn. Trong trường hợp này, tôi khuyên bạn nên sử dụng CLI gốc phản ứng để bạn có thể sửa đổi và chơi với mã gốc một cách dễ dàng.

Xin chào, tên tôi là Hayani. Tôi đã tạo subscribei.io để giúp người sáng tạo, người viết blog và những người có ảnh hưởng phát triển lượng khán giả của họ thông qua bản tin.

Tham gia danh sách Gửi thư của tôi nếu bạn muốn đọc thêm về React Native.