Неточное и ненадежное сканирование штрих -кода в веб -приложении iOSIOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Неточное и ненадежное сканирование штрих -кода в веб -приложении iOS

Сообщение Anonymous »

Я строю веб-приложение React/TypeScript (PWA-стиль), которое включает сканер штрих-кода. Сканер использует API Barcodectorector, если он поддерживается; В противном случае я возвращаюсь к @zxing/библиотеке. На iPhone сканер часто ничего не обнаруживает или, что еще хуже, читает неправильные штрих -коды. Новые iPhone также изо всех сил пытаются сосредоточиться на штрих -кодах, делая вещи еще сложнее. /> Использование как нативных, так и ZXING Sharkbacks < /li>
< /ul>
Кто -нибудь выяснил хорошие ограничения или трюки (разрешение, частота кадров и т. Д.), Которые повышают производительность на сафари iOS? Есть лучшие практики для работы по вопросам фокусировки iOS или плохого качества декодирования?import { useState, useRef, useCallback, useEffect } from 'react';
import { BrowserMultiFormatReader, IScannerControls } from '@zxing/library';

interface BarcodeResult {
code: string;
format: string;
}

export function useBarcodeScanner() {
const [state, setState] = useState({
isScanning: false,
error: null,
lastResult: null
});

const videoRef = useRef(null);
const zxingControlsRef = useRef(null);
const isInitializedRef = useRef(false);
const codeReaderRef = useRef
(null);

const getCodeReader = useCallback(() => {
if (!codeReaderRef.current) {
codeReaderRef.current = new BrowserMultiFormatReader();
}
return codeReaderRef.current;
}, []);

const stopScanning = useCallback(() => {
if (zxingControlsRef.current) {
zxingControlsRef.current.stop();
zxingControlsRef.current = null;
} else if (videoRef.current && videoRef.current.srcObject) {
const tracks = (videoRef.current.srcObject as MediaStream).getTracks();
tracks.forEach(track => { if (track.readyState === 'live') track.stop(); });
}
isInitializedRef.current = false;
setState(prev => ({ ...prev, isScanning: false }));
}, []);

const startScanning = useCallback(async (onResult: (result: BarcodeResult) => void) => {
if (isInitializedRef.current) return;

setState(prev => ({ ...prev, isScanning: true, error: null }));
isInitializedRef.current = true;

try {
if ('BarcodeDetector' in window) {
// --- Native BarcodeDetector Logic ---
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'environment',
width: { ideal: 1280, min: 640 },
height: { ideal: 720, min: 480 }
}
});
if (videoRef.current) {
videoRef.current.srcObject = stream;
videoRef.current.setAttribute('playsinline', 'true');
await videoRef.current.play();

const barcodeDetector = new (window as any).BarcodeDetector({
formats: ['ean_13', 'ean_8', 'code_128', 'code_39', 'upc_a', 'upc_e']
});

let scanLoopInterval: NodeJS.Timeout;
const scanLoop = async () => {
if (!videoRef.current || videoRef.current.paused || videoRef.current.ended || !isInitializedRef.current) {
if (scanLoopInterval) clearInterval(scanLoopInterval);
return;
}
try {
const barcodes = await barcodeDetector.detect(videoRef.current);
if (barcodes.length > 0) {
const barcode = barcodes[0];
const result: BarcodeResult = { code: barcode.rawValue, format: barcode.format };
setState(prev => ({ ...prev, lastResult: result }));
onResult(result);
stopScanning(); // Stop after successful scan
}
} catch (err) { }
};
scanLoopInterval = setInterval(scanLoop, 300);
}
} else {
// --- ZXing Fallback Logic ---
const codeReader = getCodeReader();
const videoElement = videoRef.current;
if (!videoElement) throw new Error('Video element not found for ZXing scanner.');

codeReader.decodeFromVideoDevice(undefined, videoElement, (result, error, controls) => {
if (result) {
const barcodeData: BarcodeResult = { code: result.getText(), format: result.getBarcodeFormat().toString() };
setState(prev => ({ ...prev, lastResult: barcodeData }));
onResult(barcodeData);
controls.stop();
zxingControlsRef.current = null;
isInitializedRef.current = false;
}
if (error && !error.message.includes('No MultiFormat Readers were able to decode')) {
setState(prev => ({ ...prev, error: `Camera-Error: ${error.message}` }));
stopScanning();
}
})
.then(controls => { zxingControlsRef.current = controls; })
.catch(err => {
setState(prev => ({ ...prev, isScanning: false, error: err.message || 'Fehler beim Starten des Scanners mit ZXing.' }));
stopScanning();
});
}
} catch (err: any) {
setState(prev => ({ ...prev, isScanning: false, error: err.message || 'Kamera-Zugriff oder Wiedergabe fehlgeschlagen' }));
stopScanning();
}
}, [stopScanning, getCodeReader]);

useEffect(() => { return () => stopScanning(); }, [stopScanning]);

return { ...state, videoRef, startScanning, stopScanning };
}

< /code>
barcodescanner.tsx, который отдает элемент для подачи камеры. < /p>
import React, { useEffect, useState } from 'react';
import { X, Camera, Loader2, CheckCircle, AlertCircle } from 'lucide-react';
import { useBarcodeScanner } from '../hooks/useBarcodeScanner';
import { useOpenFoodFacts } from '../hooks/useOpenFoodFacts';

interface BarcodeScannerProps {
onProductFound: (productData: any) => void;
onClose: () => void;
}

const BarcodeScanner: React.FC = ({ onProductFound, onClose }) => {
const { isScanning, error: scanError, videoRef, startScanning, stopScanning } = useBarcodeScanner();
const { loading: fetchingProduct, error: fetchError, fetchProduct, clearError } = useOpenFoodFacts();
const [scanResult, setScanResult] = useState(null);
const [productFound, setProductFound] = useState(false);

useEffect(() => {
if (!scanResult && !isScanning) {
startScanning(async (result) => {
setScanResult(result.code);
const productData = await fetchProduct(result.code);
if (productData) {
setProductFound(true);
setTimeout(() => onProductFound(productData), 1500);
}
});
}
return () => stopScanning();
}, [startScanning, stopScanning, fetchProduct, onProductFound, scanResult, isScanning]);

......

export default BarcodeScanner;


Подробнее здесь: https://stackoverflow.com/questions/796 ... os-web-app
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»