Kamera — expo-camera, QR kod skaner
Muammodan boshlaylik
Do'kon ilovasiga ikki imkoniyat kerak:
- QR / shtrix-kod skaneri — mahsulot ustidagi kodni skanerlab, uni katalogda topish
- Rasm olish — mijoz qaytariladigan mahsulotning rasmini yuboradi
Veb ilovada kamera bilan ishlash cheklangan va noqulay. Mobil ilovada esa — bu tabiiy imkoniyat.
O'rnatish
npx expo install expo-camera
app.json — ruxsat matni (38-dars):
"plugins": [
["expo-camera", { "cameraPermission": "Mahsulot QR kodini skanerlash va rasm olish uchun." }]
]
Oddiy kamera
import { CameraView, useCameraPermissions, CameraType } from 'expo-camera';
import { useRef, useState } from 'react';
import { View, Pressable, Image, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
export default function Kamera() {
const [ruxsat, soraRuxsat] = useCameraPermissions();
const [tomon, setTomon] = useState<CameraType>('back');
const [rasm, setRasm] = useState<string | null>(null);
const ref = useRef<CameraView>(null);
if (!ruxsat) return null;
if (!ruxsat.granted) return <RuxsatEkran soraRuxsat={soraRuxsat} canAskAgain={ruxsat.canAskAgain} />;
async function suratOl() {
const foto = await ref.current?.takePictureAsync({ quality: 0.7 });
if (foto) setRasm(foto.uri);
}
if (rasm) {
return (
<View style={{ flex: 1 }}>
<Image source={{ uri: rasm }} style={{ flex: 1 }} />
<View style={styles.pastki}>
<Tugma matn="Qayta olish" turi="ikkinchi" onPress={() => setRasm(null)} />
<Tugma matn="Yuborish" onPress={() => yuklash(rasm)} />
</View>
</View>
);
}
return (
<View style={{ flex: 1 }}>
<CameraView ref={ref} style={StyleSheet.absoluteFill} facing={tomon} />
<View style={styles.boshqaruv}>
<Pressable onPress={() => setTomon((t) => (t === 'back' ? 'front' : 'back'))} hitSlop={12}>
<Ionicons name="camera-reverse-outline" size={32} color="white" />
</Pressable>
<Pressable onPress={suratOl} style={styles.tushirgich} accessibilityLabel="Surat olish" />
<View style={{ width: 32 }} />
</View>
</View>
);
}
const styles = StyleSheet.create({
boshqaruv: { position: 'absolute', bottom: 48, left: 0, right: 0, flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center' },
tushirgich: { width: 72, height: 72, borderRadius: 36, backgroundColor: 'white', borderWidth: 5, borderColor: 'rgba(255,255,255,0.5)' },
pastki: { flexDirection: 'row', gap: 12, padding: 16 },
});
CameraView— kamera ko'rinishi; boshqaruv tugmalari ustigaposition: 'absolute'bilanfacing—back/fronttakePictureAsync({ quality })— rasm faylining vaqtinchalikurisini qaytaradiquality: 0.7— sifat va hajm muvozanati; 1 — juda katta fayl
[!INFO] Kamera emulyatorda cheklangan ishlaydi (Android emulyatori virtual sahna ko'rsatadi, iOS simulatorida kamera umuman yo'q). Haqiqiy telefonda sinang.
QR va shtrix-kod skaneri
import { CameraView, useCameraPermissions, BarcodeScanningResult } from 'expo-camera';
import { useRef, useState } from 'react';
import { router } from 'expo-router';
import * as Haptics from 'expo-haptics';
export default function Skaner() {
const [ruxsat, soraRuxsat] = useCameraPermissions();
const qulf = useRef(false);
const [chiroq, setChiroq] = useState(false);
if (!ruxsat?.granted) return <RuxsatEkran ruxsat={ruxsat} soraRuxsat={soraRuxsat} />;
function skanerlandi({ data, type }: BarcodeScanningResult) {
if (qulf.current) return; // ⚠️ bir xil kod soniyasiga o'nlab marta keladi
qulf.current = true;
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
if (data.startsWith('https://dokon.uz/m/')) {
const id = data.split('/').pop();
router.replace({ pathname: '/mahsulot/[id]', params: { id: id! } });
} else {
Alert.alert('Kod', `${type}: ${data}`, [{ text: 'OK', onPress: () => { qulf.current = false; } }]);
}
}
return (
<View style={{ flex: 1, backgroundColor: 'black' }}>
<CameraView
style={StyleSheet.absoluteFill}
facing="back"
enableTorch={chiroq}
barcodeScannerSettings={{ barcodeTypes: ['qr', 'ean13', 'ean8', 'code128'] }}
onBarcodeScanned={skanerlandi}
/>
{/* Ramka */}
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{ width: 250, height: 250, borderWidth: 3, borderColor: 'white', borderRadius: 20 }} />
<Text style={{ color: 'white', marginTop: 16 }}>Kodni ramka ichiga joylang</Text>
</View>
<Pressable onPress={() => setChiroq(!chiroq)} style={{ position: 'absolute', bottom: 60, alignSelf: 'center' }}>
<Ionicons name={chiroq ? 'flash' : 'flash-outline'} size={32} color="white" />
</Pressable>
</View>
);
}
Muhim jihatlar:
qulf—onBarcodeScannedkamera kodni ko'rib turgan har kadrda chaqiriladi. Busiz — o'nlab ekran ochiladi.useRef— holat emas, chunki qayta chizish kerak emas va darhol o'zgarishi kerakbarcodeTypes— faqat kerakli turlar: tezroq va xatosiz.ean13— do'kondagi mahsulotlar shtrix-kodi- Tebranish (
expo-haptics, 43-dars) — "skanerlandi" ni his qilish - Chiroq — qorong'i omborda
- QR dagi ma'lumotga ishonmang — u istalgan matn yoki zararli havola bo'lishi mumkin. Faqat kutilgan formatni qabul qiling
Ekranga qaytganda
Skanerdan mahsulotga push qilib qaytsangiz — qulf hali true. useFocusEffect bilan tiklang (26-dars):
useFocusEffect(useCallback(() => { qulf.current = false; }, []));
Kamera resurslari
Kamera — ko'p batareya va xotira sarflaydi. Tab ichida kamera ekrani bo'lsa va foydalanuvchi boshqa tabga o'tsa — kamera ishlab qolmasligi kerak:
import { useIsFocused } from '@react-navigation/native';
const fokusda = useIsFocused();
return fokusda ? <CameraView ... /> : null;
Hujjat skaneri va boshqa imkoniyatlar
- Video:
CameraView mode="video"+recordAsync(), mikrofon ruxsati bilan - Murakkab ishlov (yuz aniqlash, real vaqt filtrlar, matnni tanish) —
react-native-vision-camerakutubxonasi; development build talab qiladi
Nima uchun shunday?
Nima uchun kod skanerlash uchun maxsus API — kameradan rasm olib, keyin uni tahlil qilish mumkin emasmi?
Mumkin, lekin sekin va noqulay bo'lardi. onBarcodeScanned kodni native darajada, har bir kadrda real vaqtda aniqlaydi — iOS ning Vision va Android ning ML Kit kabi tizim kutubxonalari yordamida, apparat tezlatishi bilan. Foydalanuvchi telefonni kodga yaqinlashtiradi — va bir zumda natija. Rasm olib, JavaScript da tahlil qilish esa har bir urinish uchun soniyalar va to'g'ri burchakni topish uchun bir necha urinish degani.
Xulosa
Eslab qoling:
expo-camera:CameraView,useCameraPermissionsfacing,takePictureAsync({ quality }),enableTorch- Skaner:
barcodeScannerSettings.barcodeTypes+onBarcodeScanned useRefqulfi — bitta kod bir marta qayta ishlansin; qaytganda tiklang- QR ma'lumotiga ishonmang — formatni tekshiring
- Fokusda bo'lmaganda kamerani o'chiring (
useIsFocused) - Haqiqiy telefonda sinang
Keyingi dars
40-dars: Galereya — rasm tanlash va serverga yuklash