16. Изображения и медиа
Работа с изображениями, видео, камерой и галереей в React Native.
Image — базовый компонент
Заголовок раздела «Image — базовый компонент»import { Image } from 'react-native';
// Локальный файл<Image source={require('./assets/logo.png')} style={{ width: 200, height: 200 }} />
// Удалённый URL (размеры обязательны!)<Image source={{ uri: 'https://example.com/photo.jpg' }} style={{ width: 200, height: 200 }} resizeMode="cover" // cover | contain | stretch | center/>expo-image — лучше встроенного
Заголовок раздела «expo-image — лучше встроенного»npx expo install expo-imageimport { Image } from 'expo-image';
<Image source={imageUrl} style={{ width: 300, height: 200 }} contentFit="cover" transition={200} // Плавное появление cachePolicy="memory-disk" // Кеширование placeholder={{ blurhash: 'LKO2:N%2Tw=w]~RBVZRi};RPxuwH' }} // Блюрхэш/>Преимущества expo-image:
- Кеширование из коробки
- BlurHash / ThumbHash placeholder
- Лучшая производительность
- Поддержка SVG, GIF, WebP, AVIF
ImagePicker — выбор из галереи / камеры
Заголовок раздела «ImagePicker — выбор из галереи / камеры»npx expo install expo-image-pickerimport * as ImagePicker from 'expo-image-picker';
// Выбрать из галереиconst pickImage = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [4, 3], quality: 0.8, });
if (!result.canceled) { setImage(result.assets[0].uri); }};
// Сделать фото камеройconst takePhoto = async () => { const { status } = await ImagePicker.requestCameraPermissionsAsync(); if (status !== 'granted') return;
const result = await ImagePicker.launchCameraAsync({ allowsEditing: true, quality: 0.8, });
if (!result.canceled) { setImage(result.assets[0].uri); }};Expo Camera
Заголовок раздела «Expo Camera»npx expo install expo-cameraimport { CameraView, useCameraPermissions } from 'expo-camera';
function CameraScreen() { const [permission, requestPermission] = useCameraPermissions(); const cameraRef = useRef(null);
if (!permission?.granted) { return <Button title="Разрешить камеру" onPress={requestPermission} />; }
const takePicture = async () => { const photo = await cameraRef.current.takePictureAsync({ quality: 0.8 }); console.log(photo.uri); };
return ( <CameraView ref={cameraRef} style={{ flex: 1 }} facing="back"> <TouchableOpacity onPress={takePicture} style={styles.captureButton} /> </CameraView> );}Video — expo-av
Заголовок раздела «Video — expo-av»npx expo install expo-avimport { Video, ResizeMode } from 'expo-av';
<Video source={{ uri: 'https://example.com/video.mp4' }} style={{ width: '100%', height: 200 }} resizeMode={ResizeMode.CONTAIN} useNativeControls isLooping shouldPlay={false} onPlaybackStatusUpdate={status => { if (status.isLoaded) { console.log('Position:', status.positionMillis); } }}/>Загрузка файлов на сервер
Заголовок раздела «Загрузка файлов на сервер»const uploadImage = async (uri: string) => { const formData = new FormData(); formData.append('file', { uri, type: 'image/jpeg', name: 'photo.jpg', } as any);
const response = await fetch('https://api.example.com/upload', { method: 'POST', body: formData, headers: { 'Content-Type': 'multipart/form-data' }, });
return response.json();};