Cours React Native · Module 6: Photos, appareil photo et son

expo-camera - Contrôle avancé de la caméra

2 min de lecture ·
Dans cette leçon5

Pour un contrôle total de la caméra, utilise expo-camera !

Installation

npx expo install expo-camera

Vue caméra de base

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>Nous avons besoin d'accéder à la caméra</Text>
        <Pressable onPress={requestPermission}>
          <Text>Accorder les permissions</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>
  );
}

Prendre des photos

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>Reprendre</Text>
          </Pressable>
          <Pressable onPress={() => savePhoto(photo)}>
            <Text>Enregistrer</Text>
          </Pressable>
        </View>
      </View>
    );
  }

  return (
    <CameraView ref={cameraRef} style={styles.camera}>
      <Pressable style={styles.captureButton} onPress={takePicture}>
        <View style={styles.captureInner} />
      </Pressable>
    </CameraView>
  );
}

Scan de codes 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(
      'Code scanné !',
      result.data,
      [{ text: 'Scanner à nouveau', 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}>Pointe la caméra vers un code QR</Text>
      </View>
    </CameraView>
  );
}

Flash

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 te donne un contrôle total sur la caméra de l'appareil !

Code de cette leçon : 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('Code scanné !', result.data, [
      { text: 'Scanner à nouveau', onPress: () => setScanned(false) },
    ]);
  };

  if (!permission?.granted) {
    return (
      <View style={styles.center}>
        <Text style={styles.text}>Nous avons besoin d'accéder à la caméra</Text>
        <Pressable style={styles.button} onPress={requestPermission}>
          <Text style={styles.buttonText}>Autoriser l'accès</Text>
        </Pressable>
      </View>
    );
  }

  return (
    <CameraView
      style={styles.camera}
      barcodeScannerSettings={{ barcodeTypes: ['qr'] }}
      // TODO : connecte la prop onBarcodeScanned à la fonction handleBarCodeScanned

    >
      <View style={styles.overlay}>
        <Text style={styles.instruction}>Pointe la caméra vers un QR code</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 },
});

Entrées de la documentation utilisées dans cette leçon

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Quel composant affiche l'aperçu de la caméra dans expo-camera ?

  2. 2. Quelles valeurs la prop 'facing' accepte-t-elle dans CameraView ?

Tâches pratiques dans le jeu

  • Tri horizontal

    Ordonne la prise d'une photo :

  • Éditeur de code

    Complète le code du scanner avec onBarcodeScanned.

Articles utiles