💻
React Native
  • 👨‍💻Full-Stack Web Developer
  • 📚Теорія
    • 1️⃣Налаштування робочого середовища
      • Вступ
      • Налаштування середовища розробки
      • Перший проект
      • Налаштування емуляції Android (Android Studio + JDK)
      • Налаштування емуляції Iphone (Xcode)
      • Запуск проекту на віртуальних пристроях
      • Expo Snack
    • 2️⃣Верстка і стилізація
      • Функціональні та класові компоненти
      • Базові компоненти
      • Фундаментальні концепції React в React Native
      • Стилізація компонентів
      • Стилізація залежно від платформи
      • Кольори
      • Зображення
      • Векторна графіка
      • Розташування компонентів
      • Робота зі шрифтами
      • Колекції даних
      • Дебаг застосунку
    • 3️⃣Обробка подій
      • Обробка подій
      • Обробка текстових інпутів
      • Інпути в фокусі
      • Форма для збору даних
      • Робота з клавіатурою
      • Перехоплення подій
    • 4️⃣Навігація
      • Підключення навігації
      • Перемикання екранів
      • Передача параметрів між екранами
      • Хедер екрану
      • Вкладена навігація
      • Нижня навігація
    • 5️⃣Нативні компоненти
      • Камера
      • Мапи
      • Геолокація
    • 👷Практика
      • 1️⃣Завдання 1
      • 2️⃣Завдання 2
      • 3️⃣Завдання 3
      • 4️⃣Завдання 4
      • 5️⃣Завдання 5
      • 6️⃣Завдання 6
      • 7️⃣Завдання 7
    • Додаткові покликання
  • Про мене
    • Про мене
Powered by GitBook
On this page
  1. Теорія
  2. Нативні компоненти

Камера

Для роботи в телефоні з камерою використовують додатково такі пакети:

  • expo-camera - надає методи роботи з камерою

  • expo-media-library - надає методи для збереження фото в пам'ять телефону

Встановлюємо пакети:

terminal
npx expo install expo-camera
terminal
npx expo install expo-media-library

Підключаємо бібліотеки для роботи з камерою і медіатекою.

import { Camera } from "expo-camera";
import * as MediaLibrary from "expo-media-library";

Для коректної роботи камери та запису на телефон, потрібно отримати дозвіл від користувача. У камери є метод - Camera.requestCameraPermissionsAsync(), а у медіа-бібліотеці - MediaLibrary.requestPermissionsAsync().

Спочатку визначимо стейт в якому зберігатимемо значення чи має програма доступ до камери. Дефолтне значення null.

const [hasPermission, setHasPermission] = useState(null);

і при першому завантаженні скріна один раз запитуємо дозвіл до камери і медіатеки.

useEffect(() => {
  (async () => {
    const { status } = await Camera.requestPermissionsAsync();
    await MediaLibrary.requestPermissionsAsync();

    setHasPermission(status === "granted");
  })();
}, []);

В залежності від значення цього стейту і рендеримо скрін. Скрін першого запуску:

if (hasPermission === null) {
  return <View />;
}

Якщо користувач скасував доступ до камери і медіатеки.

if (hasPermission === false) {
  return <Text>No access to camera</Text>;
}

Якщо доступ до камери і медіатеки надано, то рендеримо скрін. Його верстка буде розглянута далі.

У компонента Camera є проп - type. Він визначає тип камери: основна (back) або фронтальна (front).

Визначимо змінну, яка буде зберігати тип обраної камери:

const [type, setType] = useState(Camera.Constants.Type.back);

Якщо ми хочемо відображення камери на весь екран, то кладемо його в компонент View (container) і також розтягаємо на весь екран. А додатковий функціонал можна розмістити всередині компоненту Camera.

<View style={{ flex: 1 }}>
     <Camera
       style={{ flex: 1 }}
       type={type}
     >
     
    </Camera>
</View>

Якщо ми хочемо відображення камери розмістити не на весь екран, а обмежити в рамках компоненту View, то огортаємо камеру цим компонентом і стилями задаємо розміри.

<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
  <View style={{ backgroundColor: "red", width: 200, height: 200 }}>
     <Camera style={{ flex: 1 }} type={type}>
     
     </Camera>
  </View>
</View>

Далі розглянемо варіант, що у нас на весь екран буде показуватися зображення з камери.

Визначимо всередині компонента Камери кнопку при натиску на яку буде змінюватися стейт type, який визначає, яка камера активна:

<TouchableOpacity
  style={{flex: 0.1, alignSelf: "flex-end",}}
  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>

Щоб зробити знімок - потрібно отримати посилання на камеру, використовуючи ref, і вже у цього об'єкта викликати метод takePictureAsync(). Результатом його роботи буде об'єкт з ключем uri, де буде зберігатися посилання на фото.

Передаємо це посилання методу MediaLibrary.createAssetAsync(uri) і фото збережеться в пам'ять телефону.

          <TouchableOpacity
            style={styles.button}
            onPress={async () => {
              if (cameraRef) {
                const { uri } = await cameraRef.takePictureAsync();
                await MediaLibrary.createAssetAsync(uri);
              }
            }}
          >
            <View style={styles.takePhotoOut}>
              <View style={styles.takePhotoInner}></View>
            </View>
          </TouchableOpacity>
Резервний код
App.js
import React, { useState, useEffect, useRef } from "react";
import { Text, View, TouchableOpacity, StyleSheet } from "react-native";
import { Camera } from "expo-camera";
import * as MediaLibrary from "expo-media-library";

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

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      await MediaLibrary.requestPermissionsAsync();

      setHasPermission(status === "granted");
    })();
  }, []);

  if (hasPermission === null) {
    return <View />;
  }
  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  return (
    <View style={styles.container}>
      <Camera style={styles.camera} type={type} ref={setCameraRef}>
        <View style={styles.photoView}>
          <TouchableOpacity
            style={styles.flipContainer}
            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
            style={styles.button}
            onPress={async () => {
              if (cameraRef) {
                const { uri } = await cameraRef.takePictureAsync();
                await MediaLibrary.createAssetAsync(uri);
              }
            }}
          >
            <View style={styles.takePhotoOut}>
              <View style={styles.takePhotoInner}></View>
            </View>
          </TouchableOpacity>
        </View>
      </Camera>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
  photoView: {
    flex: 1,
    backgroundColor: "transparent",
    justifyContent: "flex-end",
  },

  flipContainer: {
    flex: 0.1,
    alignSelf: "flex-end",
  },

  button: { alignSelf: "center" },

  takePhotoOut: {
    borderWidth: 2,
    borderColor: "white",
    height: 50,
    width: 50,
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    borderRadius: 50,
  },

  takePhotoInner: {
    borderWidth: 2,
    borderColor: "white",
    height: 40,
    width: 40,
    backgroundColor: "white",
    borderRadius: 50,
  },
});

Документація:

PreviousНативні компонентиNextМапи

Last updated 1 year ago

Протестувати коректно камеру в не вийде, тому використовуйте налагодження цього функціоналу на справжньому пристрої.

📚
5️⃣
симуляторах
Expo Camera
Expo MediaLibrary