Kurs React Native · Moduł 6: Zdjęcia, kamera i dźwięk
expo-camera - Zaawansowana obsługa kamery
W tej lekcji5
Dla pełnej kontroli nad kamerą użyj expo-camera!
Instalacja
npx expo install expo-cameraPodstawowy widok kamery
import { CameraView, CameraType, useCameraPermissions } from 'expo-camera';
import { useState, useRef } from 'react';
function CameraScreen() {
const [facing, setFacing] = useState<CameraType>('back');
const [permission, requestPermission] = useCameraPermissions();
const cameraRef = useRef<CameraView>(null);
if (!permission) {
return <View />;
}
if (!permission.granted) {
return (
<View style={styles.container}>
<Text>Potrzebujemy dostępu do kamery</Text>
<Pressable onPress={requestPermission}>
<Text>Przyznaj uprawnienia</Text>
</Pressable>
</View>
);
}
const toggleCameraFacing = () => {
setFacing((current) => (current === 'back' ? 'front' : 'back'));
};
return (
<View style={styles.container}>
<CameraView
ref={cameraRef}
style={styles.camera}
facing={facing}
>
<View style={styles.controls}>
<Pressable onPress={toggleCameraFacing}>
<Ionicons name="camera-reverse" size={32} color="white" />
</Pressable>
</View>
</CameraView>
</View>
);
}Robienie zdjęć
function CameraWithCapture() {
const cameraRef = useRef<CameraView>(null);
const [photo, setPhoto] = useState<string | null>(null);
const takePicture = async () => {
if (cameraRef.current) {
const photo = await cameraRef.current.takePictureAsync({
quality: 0.8,
base64: false,
exif: true,
});
if (photo) {
setPhoto(photo.uri);
}
}
};
if (photo) {
return (
<View style={styles.previewContainer}>
<Image source={{ uri: photo }} style={styles.preview} />
<View style={styles.previewButtons}>
<Pressable onPress={() => setPhoto(null)}>
<Text>Powtórz</Text>
</Pressable>
<Pressable onPress={() => savePhoto(photo)}>
<Text>Zapisz</Text>
</Pressable>
</View>
</View>
);
}
return (
<CameraView ref={cameraRef} style={styles.camera}>
<Pressable style={styles.captureButton} onPress={takePicture}>
<View style={styles.captureInner} />
</Pressable>
</CameraView>
);
}Skanowanie kodów QR
import { CameraView, useCameraPermissions, BarcodeScanningResult } from 'expo-camera';
function QRScanner() {
const [permission, requestPermission] = useCameraPermissions();
const [scanned, setScanned] = useState(false);
const handleBarCodeScanned = (result: BarcodeScanningResult) => {
if (scanned) return;
setScanned(true);
Alert.alert(
'Zeskanowano kod!',
result.data,
[{ text: 'Skanuj ponownie', onPress: () => setScanned(false) }]
);
};
return (
<CameraView
style={styles.camera}
barcodeScannerSettings={{
barcodeTypes: ['qr', 'ean13', 'ean8'],
}}
onBarcodeScanned={handleBarCodeScanned}
>
<View style={styles.overlay}>
<View style={styles.scanArea} />
<Text style={styles.instruction}>Skieruj kamerę na kod QR</Text>
</View>
</CameraView>
);
}Lampa błyskowa
function CameraWithFlash() {
const [flash, setFlash] = useState<'off' | 'on' | 'auto'>('off');
const toggleFlash = () => {
setFlash((current) => {
if (current === 'off') return 'on';
if (current === 'on') return 'auto';
return 'off';
});
};
return (
<CameraView style={styles.camera} flash={flash}>
<Pressable onPress={toggleFlash}>
<Ionicons
name={flash === 'off' ? 'flash-off' : flash === 'on' ? 'flash' : 'flash-outline'}
size={28}
color="white"
/>
</Pressable>
</CameraView>
);
}expo-camera daje pełną kontrolę nad kamerą urządzenia!
Kod do tej lekcji: App.tsx
import React, { useState } from 'react';
import { View, Text, Pressable, StyleSheet, Alert } from 'react-native';
import { CameraView, useCameraPermissions, BarcodeScanningResult } from 'expo-camera';
export default function App() {
const [permission, requestPermission] = useCameraPermissions();
const [scanned, setScanned] = useState(false);
const handleBarCodeScanned = (result: BarcodeScanningResult) => {
if (scanned) return;
setScanned(true);
Alert.alert('Zeskanowano kod!', result.data, [
{ text: 'Skanuj ponownie', onPress: () => setScanned(false) },
]);
};
if (!permission?.granted) {
return (
<View style={styles.center}>
<Text style={styles.text}>Potrzebujemy dostępu do kamery</Text>
<Pressable style={styles.button} onPress={requestPermission}>
<Text style={styles.buttonText}>Przyznaj uprawnienia</Text>
</Pressable>
</View>
);
}
return (
<CameraView
style={styles.camera}
barcodeScannerSettings={{ barcodeTypes: ['qr'] }}
// TODO: podłącz prop onBarcodeScanned do funkcji handleBarCodeScanned
>
<View style={styles.overlay}>
<Text style={styles.instruction}>Skieruj kamerę na kod QR</Text>
</View>
</CameraView>
);
}
const styles = StyleSheet.create({
center: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276' },
camera: { flex: 1 },
overlay: { flex: 1, justifyContent: 'flex-end', alignItems: 'center', paddingBottom: 60 },
instruction: { color: '#fff', fontSize: 16, backgroundColor: 'rgba(0,0,0,0.5)', padding: 10, borderRadius: 8 },
text: { color: '#fff', fontSize: 16, marginBottom: 16 },
button: { backgroundColor: '#2980b9', padding: 12, borderRadius: 8 },
buttonText: { color: '#fff', fontSize: 16 },
});Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jaki komponent wyświetla podgląd kamery w expo-camera?
2. Jakie wartości przyjmuje prop 'facing' w CameraView?
Zadania praktyczne w grze
- Układanie w poziomie
Ułóż robienie zdjęcia:
- Edytor kodu
Uzupełnij kod skanera z onBarcodeScanned.