Kurs React Native · Moduł 6: Zdjęcia, kamera i dźwięk

expo-camera - Zaawansowana obsługa kamery

2 min czytania ·
W tej lekcji5

Dla pełnej kontroli nad kamerą użyj expo-camera!

Instalacja

npx expo install expo-camera

Podstawowy 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. 1. Jaki komponent wyświetla podgląd kamery w expo-camera?

  2. 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.

Przydatne artykuły