Камера
Для роботи в телефоні з камерою використовують додатково такі пакети:
expo-camera - надає методи роботи з камерою
expo-media-library - надає методи для збереження фото в пам'ять телефону
Встановлюємо пакети:
npx expo install expo-camera
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>
Документація:
Last updated