Я только начал использовать React Native с Expo, поэтому я немного смущен. Итак, я сделал компонент камеры, который импортировал на главный экран. Все выглядит хорошо. Но я не могу фотографировать. Я не могу щелкнуть значок привязки и сохранить изображение. Есть ли компонент, который я пропустил?
Я разместил только класс CameraComponent ниже.
Camera.js
class CameraComponent extends Component {
state = {
hasCameraPermission: null,
type: Camera.Constants.Type.back
}
async componentWillMount() {
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, justifyContent: 'space-between' }}
type = {this.state.type}
>
<Header
searchBar
rounded
style = {{
position: 'absolute',
backgroundColor: 'transparent',
left: 0,
top: 0,
right: 0,
zIndex: 100,
alignItems: 'center'
}}
>
<View style = {{ flexDirection: 'row', flex: 4 }}>
<Ionicons name = "md-camera" style = {{ color: 'white' }} />
<Item style = {{ backgroundColor: 'transparent' }}>
<Icon name = "ios-search" style = {{ color: 'white', fontSize: 24, fontWeight: 'bold' }}></Icon>
</Item>
</View>
<View style = {{ flexDirection: 'row', flex: 2, justifyContent: 'space-around' }}>
<Icon name = "ios-flash" style = {{ color: 'white', fontWeight: 'bold' }} />
<Icon
onPress = {() => {
this.setState({
type: this.state.type === Camera.Constants.Type.back ?
Camera.Constants.Type.front :
Camera.Constants.Type.back
})
}}
name = "ios-reverse-camera"
style = {{ color: 'white', fontWeight: 'bold' }}
/>
</View>
</Header>
<View style = {{ flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 30, marginBottom: 15, alignItems: 'flex-end' }}>
<Ionicons name = "ios-map" style = {{ color: 'white', fontSize: 36 }}></Ionicons>
<View></View>
<View style = {{ alignItems: 'center' }}>
<MaterialCommunityIcons name = "circle-outline" // This is the icon which should take and save image
style = {{ color: 'white', fontSize: 100 }}
></MaterialCommunityIcons>
<Icon name = "ios-images" style = {{ color: 'white', fontSize: 36 }} />
</View>
</View>
</Camera>
</View>
)
}
}
}
export default CameraComponent;
Значок в центре круга должен автоматически сделать и сохранить изображение.





Вы пытаетесь сделать это на реальном физическом устройстве? Снимать фото с помощью эмулятора не получится.
Таким образом, вам нужно указать свой «значок круга», чтобы сделать снимок. Сначала я бы добавил ссылку на вашу камеру вот так
<Camera style = {{ flex: 1 }}
ref = { (ref) => {this.camera = ref} }
type = {this.state.type}>
затем создайте функцию, которая фактически сообщает вашему приложению сделать снимок:
async snapPhoto() {
console.info('Button Pressed');
if (this.camera) {
console.info('Taking photo');
const options = { quality: 1, base64: true, fixOrientation: true,
exif: true};
await this.camera.takePictureAsync(options).then(photo => {
photo.exif.Orientation = 1;
console.info(photo);
});
}
}
Теперь сделайте так, чтобы на вашем значке была кнопка onPress (), чтобы сделать снимок. Я сделал что-то подобное.
<TouchableOpacity style = {styles.captureButton} onPress = {this.snapPhoto.bind(this)}>
<Image style = {{width: 100, height: 100}} source = {require('../assets/capture.png')}
/>
</TouchableOpacity>
Вы также можете создать представление, которое отображает предварительный просмотр изображения или что-то подобное. В документации Expo есть довольно хороший пример начала работы. Обратите внимание, что Expo создает кешированную папку под названием «Камера», и именно там изначально находится изображение.
Документация для этого находится здесь: docs.expo.io/versions/latest/sdk/camera
Вам нужно будет добавить ссылку в класс Camera, чтобы иметь возможность вызывать его функцию takePictureAsync в вашем собственном методе «handle».
cameraRef = React.createRef();
<Camera ref = {this.cameraRef}>...</Camera>
Не забывайте ".current" при вызове метода указанной камеры.
handlePhoto = async () => {
if (this.cameraRef){
let photo = await this.cameraRef.current.takePictureAsync();
console.info(photo);
}
}
Затем просто вызовите свой метод «handle» на сенсорном элементе, действующем как кнопка фотосъемки.
<TouchableOpacity
style = {{width:60, height:60, borderRadius:30, backgroundColor:"#fff"}}
onPress = {this.handlePhoto} />
Вы должны увидеть фотографию, зарегистрированную в вашей консоли.
Вы можете использовать onPictureSaved при возврате асинхронной функции takePictureAsync, чтобы вы могли захватить объект фотографии:
takePicture = () => {
if (this.camera) {
this.camera.takePictureAsync({ onPictureSaved: this.onPictureSaved });
}
};
onPictureSaved = photo => {
console.info(photo);
}
В представлении у вас будет компонент Camera, у которого есть ссылка:
<Camera style = {styles.camera} type = {this.state.type} ref = {(ref) => { this.camera = ref }} >
А также кнопка, которая будет вызывать функцию takePicture при нажатии:
<TouchableOpacity style = {styles.captureButton} onPress = {this.takePicture} />
Вы можете сделать это и в функциональном компоненте, используя ссылку, созданную с помощью React Hook. Вот пример, основанный на компоненте камеры expo SDK 38 https://docs.expo.io/versions/v38.0.0/sdk/camera/
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const ref = useRef(null)
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
_takePhoto = async () => {
const photo = await ref.current.takePictureAsync()
console.debug(photo)
}
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style = {{ flex: 1 }}>
<Camera style = {{ flex: 1 }} type = {type} ref = {ref}>
<View
style = {{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<TouchableOpacity
style = {{
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
}}
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
onPress = {_takePhoto}
>
<Text>Snap Photo</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
Я не проверял, как выглядит пользовательский интерфейс для этого, но главное - использовать React.useRef и прикрепить ссылку к вашему компоненту <Camera/>. Затем вы можете вызвать ref.current.takePictureAsync, чтобы захватить и получить доступ к новому образу. Посмотрите ниже, чтобы увидеть важные соответствующие фрагменты для фотосъемки.
import React from 'react'
/* ... other imports
*/
export default CameraScene = () => {
/* ... other state and permission logic
*/
const ref = useRef(null)
const _takePhoto = async () => {
const photo = await ref.current.takePictureAsync()
console.debug(photo)
}
return (
<Camera style = {{flex: 1}} ref = {ref}> /* ...
... other ui logic
*/
</Camera>
)
}
Подробнее про useRef здесь https://reactjs.org/docs/hooks-reference.html#useref)
Привет, где мне использовать нижний код?
Я использую клиент expo на устройстве Android для запуска приложения. Я сканирую qr-код.