Come scansionare i codici QR nei browser Web con Web Workers e jsQR

0
197
shisu_ka/Shutterstock.com

I codici QR sono diventati molto più popolari negli ultimi anni. Sono ampiamente utilizzati per fornire informazioni e facilitare i check-in. Sebbene si trovi più comunemente come parte delle app mobili native, puoi anche incorporare scansioni QR nei tuoi siti web.

Ecco come utilizzare la popolare libreria jsQR in combinazione con Web Workers per offrire un'esperienza di scansione QR ad alte prestazioni sul web. Daremo per scontato che tu abbia già familiarità con le basi di JavaScript e che tu abbia un sito funzionante a cui sei pronto per aggiungere il tuo codice.

1. Per iniziare

Inizia scaricando la libreria jsQR in formato distribuibile precompilato. Assicurati che sia accessibile pubblicamente sul tuo server web; in questo articolo, supponiamo che l'URL sia /jsQR.js. jsQR è disponibile anche come pacchetto npm se hai configurato una routine di compilazione.

Questo pacchetto fornisce il rilevamento in tempo reale dei codici QR visibili in un flusso video. Recupera i dati all'interno del codice e li fornisce alla tua applicazione.

2. Ottenere un feed della videocamera

Il passaggio successivo consiste nell'acquisire un MediaStream dal browser. Usa l'API mediaDevices per ottenere un nuovo stream dalla videocamera dell'utente:

const getCamera = asincrono () => {   se (!navigator.mediaDevices) { genera un nuovo errore("API mediaDevices non disponibile."); }   const devices = attendi navigator.mediaDevices.enumerateDevices(); const telecamere = devices.filter(d => (d.kind === "ingresso video")); telecamere di ritorno[0];   }; Pubblicità

Stiamo selezionando la prima telecamera che viene trovata. È possibile aggiungere una logica extra per abilitare la selezione di una telecamera specifica indicata dall'utente. In un'app reale, dovresti anche migliorare la gestione degli errori quando l'API mediaDevices non è disponibile. Ciò potrebbe essere dovuto al fatto che l'utente utilizza un browser Web obsoleto o ha bloccato in modo permanente l'autorizzazione di accesso alla videocamera.

Utilizzare la funzione getCamera() per acquisire il flusso video. Allega lo stream a un <video> elemento in modo che possa essere riprodotto e mostrato all'utente:

<riproduzione automatica del video="vero" id="video" muto="vero" /> const stream = attendi getCamera(); const video = document.getElementById("video");   video.srcObject = flusso; attendi video.play();

3. Creazione di una tela

Il passaggio successivo è creare un elemento tela. I dati video verranno trasmessi dalla telecamera alla tela dove i pixel dell'immagine verranno estratti e inviati a jsQR. La tela deve essere dimensionata in modo che corrisponda alle dimensioni del flusso video.

const videoTracks = attendi stream.getVideoTracks(); const videoTrackSettings = videoTracks[0].getSettings();   const canvas = document.createElement("canvas"); canvas.height = videoTrackSettings.height; canvas.width = videoTrackSettings.width;   const canvasContext = canvas.getContext("2d");

Il contesto della tela verrà utilizzato nel passaggio successivo per disegnare ogni fotogramma del flusso video sulla tela.

4. Aggiunta di jsQR

Aggiungi jsQR al tuo codice dopo. L'esecuzione di jsQR in un web worker consente al browser di delegarlo a un processo in background, migliorando le prestazioni. jsQR deve scansionare ogni fotogramma video, quindi eseguirlo nel thread JavaScript principale può causare gravi rallentamenti sui dispositivi di fascia bassa.

Il thread principale e il tuo lavoratore web possono comunicare utilizzando i messaggi. Il tuo thread principale invierà un messaggio al lavoratore jsQR ogni volta che è disponibile un nuovo frame video. Il lavoratore ispezionerà quel frame per i codici QR nel suo thread in background, quindi invierà un messaggio al thread principale quando il frame è stato elaborato.

Annuncio

Carica il tuo lavoratore nel tuo codice JavaScript principale e aggiungi un ascoltatore di messaggi:

const qrWorker = nuovo lavoratore("/qr-worker.js");   qrWorker.addEventListener("message", ({data}) => {   se (dati) { //Dati dal codice QR disponibili ////Gestire una scansione riuscita qui. } altrimenti { //Nessun codice QR rilevato in questo frame ////Invia il frame successivo all'operatore QR //ora (questo codice è introdotto di seguito). spunta(); }   });

Quindi aggiungi qr-worker.js al tuo progetto. Questo deve essere pubblicamente accessibile all'URL fornito al costruttore Worker. I browser scaricheranno il web worker nel momento in cui è necessario.

importScripts("jsQR.js");   self.addEventListener("messaggio", e => { const {dati, larghezza, altezza} = e.dati; const qrData = jsQR(dati, larghezza, altezza); self.postMessage(qrData); });

La funzione importScripts() scarica la libreria jsQR. Questa chiamata è equivalente a un <script> tag nel tuo HTML ma rende i contenuti dello script disponibili al tuo lavoratore web.

Un ascoltatore di messaggi viene aggiunto per ricevere eventi dal thread principale del tuo JavaScript. Ogni evento deve includere i dati, la larghezza e l'altezza di un fotogramma video trasmesso in streaming dalla telecamera. Questi valori vengono inviati a jsQR che tenterà di rilevare un codice QR all'interno del frame. Il risultato viene ripubblicato nel thread principale.

5. Cablaggio di tutto

Il passaggio finale consiste nel creare un ciclo di aggiornamento che fornisca periodicamente frame video al lavoratore jsQR.

const updateJsQr = () => { canvasContext.drawImage(video, 0, 0, canvas.width, canvas.height); const imageData = canvasContext.getImageData(0, 0, canvas.width, canvas.height); qrWorker.postMessage({data: imageData, altezza: canvas.height, larghezza: canvas.width}); }   const tick = () => requestAnimationFrame(updateJsQr);   spunta();

La funzione tick() richiede al browser di dedicare tempo alla chiamata di updateJsQr() prima del successivo repaint. Questa funzione ottiene il fotogramma video corrente, lo disegna sulla tela e quindi estrae i dati dell'immagine risultanti pronti per essere passati a jsQR. Il metodo postMessage() sull'istanza di lavoro invia effettivamente i dati.

Annuncio

Il lavoratore agirà poi sui dati come indicato nel codice sopra. Il risultato del rilevamento viene comunicato al thread principale che lo elabora come mostrato nel passaggio 4. Quando viene rilevato un codice QR, l'applicazione dovrebbe utilizzare i dati recuperati per andare avanti nel suo flusso. Quando non viene rilevato alcun codice, tick() viene chiamato nuovamente per passare il frame successivo all'operatore QR, pronto per la valutazione.

Questo meccanismo ti assicura di non sovraccaricare il browser eseguendo più rilevamenti di frame contemporaneamente. Ogni chiamata a jsQR() è potenzialmente costosa, quindi è necessario attendere che il risultato sia noto prima di pianificarne un'altra. Il ciclo viene sostenuto solo fino a quando non si ottiene un risultato positivo, con jsQR che gestisce un frame alla volta. L'interfaccia utente del tuo sito e l'anteprima della videocamera in tempo reale rimarranno reattive per tutto il tempo mentre l'operatore viene eseguito in modo indipendente in background.

6. jsQR Result Data

Ogni chiamata riuscita a jsQR() restituisce un oggetto risultato con le seguenti proprietà:

  • data – Stringa i dati estratti dal codice QR (questa è l'unica proprietà utilizzata nell'esempio sopra).
  • binaryData – Un Uint8ClampedArray contenente i byte non elaborati letti dal codice QR.
  • versione – Rilevata versione del codice QR.
  • posizione – Un oggetto che descrive la posizione del codice QR rilevato all'interno del fotogramma video, inclusi i punti per ogni angolo.

Non sono disponibili dati quando jsQR non riesce a rilevare un codice nell'immagine fornita.< /p>

7. Conclusione

La combinazione di jsQR con Web Workers ti consente di implementare scansioni di codici QR ad alte prestazioni nella tua applicazione web. I codici QR sono un meccanismo di condivisione dei dati facile e conveniente con cui la maggior parte degli utenti mobili ora ha familiarità.

Anche se puoi usare jsQR come parte del tuo ciclo principale, dovresti implementare una limitazione aggressiva per mantenere la tua interfaccia utente reattiva. Ciò comporterebbe un ritardo maggiore prima di un rilevamento riuscito. I Web Worker sono supportati in tutti i browser moderni e forniscono un notevole incremento delle prestazioni a questa soluzione, consentendo scansioni di frazioni di secondo in condizioni di illuminazione ottimali.