Hoe QR-codes in webbrowsers te scannen met webwerkers en jsQR

0
57
shisu_ka/Shutterstock.com

QR-codes zijn de laatste jaren veel populairder geworden. Ze worden veel gebruikt om informatie te verstrekken en check-ins te vergemakkelijken. Hoewel u deze meestal vindt als onderdeel van native mobiele apps, kunt u ook QR-scans in uw websites opnemen.

Hier leest u hoe u de populaire jsQR-bibliotheek in combinatie met Web Workers kunt gebruiken om een ​​hoogwaardige QR-scanervaring op internet te bieden. We gaan ervan uit dat u al bekend bent met de basisprincipes van JavaScript en dat u een functionerende site heeft waaraan u uw code kunt toevoegen.

1. Aan de slag

Begin met het downloaden van de jsQR-bibliotheek in een voorgecompileerd distribueerbaar formaat. Zorg ervoor dat het openbaar toegankelijk is op uw webserver; in dit artikel gaan we ervan uit dat de URL /jsQR.js is. jsQR is ook beschikbaar als een npm-pakket als je een build-routine hebt geconfigureerd.

Dit pakket biedt realtime detectie van QR-codes die zichtbaar zijn in een videostream. Het haalt de gegevens binnen de code op en levert deze aan uw applicatie.

2. Een camerafeed verkrijgen

De volgende stap is het verkrijgen van een MediaStream van de browser. Gebruik de mediaDevices API om een ​​nieuwe stream van de camera van de gebruiker te krijgen:

const getCamera = asynchrone () => {   als (!navigator.mediaDevices) { gooi nieuwe fout("mediaDevices API niet beschikbaar."); }   const devices = wacht navigator.mediaDevices.enumerateDevices(); const camera's = devices.filter(d => (d.kind === "video-ingang")); retour camera's[0];   }; Advertentie

We selecteren de eerste camera die wordt gevonden. Je zou extra logica kunnen toevoegen om de selectie van een door de gebruiker aangegeven specifieke camera mogelijk te maken. In een echte app moet je ook de foutafhandeling verbeteren wanneer de mediaDevices API niet beschikbaar is. Dit kan zijn omdat de gebruiker zich in een oude webbrowser bevindt of omdat hij de toegangsrechten voor de camera permanent heeft geblokkeerd.

Gebruik de functie getCamera() om de videostream op te halen. Voeg de stream toe aan een <video> element zodat het kan worden afgespeeld en weergegeven aan de gebruiker:

<video automatisch afspelen="true" id="video" gedempt ="waar" /> const stream = wacht op getCamera(); const video = document.getElementById("video");   video.srcObject = stroom; wacht op video.play();

3. Een canvas maken

De volgende stap is het maken van een canvaselement. De videogegevens worden van de camera naar het canvas gestreamd, waar de beeldpixels worden geëxtraheerd en naar jsQR worden gevoerd. Het formaat van het canvas moet overeenkomen met de afmetingen van de videostream.

const videoTracks = wacht op 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");

De canvascontext wordt in de volgende stap gebruikt om elk frame van de videostream op het canvas te tekenen.

4. JsQR toevoegen

Voeg vervolgens jsQR toe aan uw code. Door jsQR in een webwerker uit te voeren, kan de browser het delegeren naar een achtergrondproces, waardoor de prestaties worden verbeterd. jsQR moet elk videoframe scannen, dus het uitvoeren ervan in uw JavaScript-hoofdthread kan ernstige vertragingen veroorzaken op low-end apparaten.

De hoofdthread en uw webwerker kunnen communiceren met behulp van berichten. Uw hoofdthread zal de jsQR-werker een bericht sturen telkens wanneer een nieuw videoframe beschikbaar is. De werknemer inspecteert dat frame op QR-codes in de achtergrondthread en stuurt vervolgens een bericht naar de hoofdthread wanneer het frame is verwerkt.

Advertentie

Laad uw worker in uw JavaScript-hoofdcode en voeg toe een berichtluisteraar:

const qrWorker = nieuwe Worker("/qr-worker.js");   qrWorker.addEventListener("message", ({data}) => {   als (gegevens) { //Gegevens van QR-code beschikbaar ////Voer hier een succesvolle scan uit. } anders { //Geen QR-code gedetecteerd in dit frame ////Voer het volgende frame naar de QR-werker //nu (deze code wordt hieronder geïntroduceerd). vink aan(); }   });

Voeg vervolgens qr-worker.js toe aan uw project. Dit moet openbaar toegankelijk zijn op de URL die aan de Worker-constructor is gegeven. Browsers zullen de webwerker downloaden op het moment dat het nodig is.

importScripts("jsQR.js");   self.addEventListener("message", e => { const "data, breedte, hoogte" = e.gegevens; const qrData = jsQR(data, breedte, hoogte); self.postMessage(qrData); });

De functie importScripts() downloadt de jsQR-bibliotheek. Deze aanroep is gelijk aan een <script> tag in uw HTML, maar maakt de inhoud van het script beschikbaar voor uw webwerker.

Er wordt een berichtlistener toegevoegd om gebeurtenissen van de hoofdthread van uw JavaScript te ontvangen. Elke gebeurtenis moet de gegevens, breedte en hoogte bevatten van een videoframe dat vanaf de camera wordt gestreamd. Deze waarden worden doorgegeven aan jsQR, die zal proberen een QR-code binnen het frame te detecteren. Het resultaat wordt teruggeplaatst in de hoofdthread.

5. Alles aansluiten

De laatste stap is het maken van een updatelus die periodiek videoframes aan de jsQR-werker voedt.

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, hoogte: canvas.height, breedte: canvas.width}); }   const vinkje = () => requestAnimationFrame(updateJsQr);   vink aan();

De functie tick() vraagt ​​de browser tijd toe te wijzen aan het aanroepen van updateJsQr() vóór de volgende repaint. Deze functie haalt het huidige videoframe op, tekent het naar het canvas en haalt vervolgens de resulterende afbeeldingsgegevens tevoorschijn die klaar zijn om door te geven aan jsQR. De methode postMessage() op de worker-instantie verzendt de gegevens daadwerkelijk.

Advertentie

De werknemer zal dan handelen op basis van de gegevens zoals weergegeven in de bovenstaande code. Het detectieresultaat wordt teruggecommuniceerd naar de hoofdthread die het verwerkt zoals weergegeven in stap 4. Wanneer een QR-code wordt gedetecteerd, moet uw toepassing de opgehaalde gegevens gebruiken om verder te gaan in de stroom. Als er geen gedetecteerde code is, wordt tick() opnieuw aangeroepen om het volgende frame door te geven aan de QR-werker, klaar voor beoordeling.

Dit mechanisme zorgt ervoor dat u de browser niet overbelast door meerdere framedetecties tegelijk uit te voeren. Elke aanroep naar jsQR() is potentieel duur, dus u wilt wachten tot het resultaat bekend is voordat u een nieuwe inplant. De lus wordt alleen volgehouden totdat een succesvol resultaat is verkregen, waarbij jsQR één frame per keer afhandelt. De gebruikersinterface van uw site en het realtime cameravoorbeeld blijven responsief terwijl de werknemer onafhankelijk op de achtergrond werkt.

6. jsQR-resultaatgegevens

Elke succesvolle aanroep van jsQR() retourneert een resultaatobject met de volgende eigenschappen:

  • data – Tekenreeksgegevens geëxtraheerd uit de QR-code (dit is de enige eigenschap die in het bovenstaande voorbeeld wordt gebruikt).
  • binaire gegevens – Een Uint8ClampedArray met de onbewerkte bytes die uit de QR-code worden gelezen.
  • versie – Versie van QR-code gedetecteerd.
  • locatie – Een object dat de positie van de gedetecteerde QR-code binnen het videoframe beschrijft, inclusief punten voor elke hoek.

Er zijn geen gegevens beschikbaar wanneer jsQR geen code kan detecteren in de geleverde afbeelding.< /p>

7. Conclusie

Door jsQR te combineren met Web Workers kunt u hoogwaardige QR-codescans in uw webtoepassing implementeren. QR-codes zijn een eenvoudig en handig mechanisme voor het delen van gegevens waarmee de meeste mobiele gebruikers nu bekend zijn.

Hoewel u jsQR als onderdeel van uw hoofdlus zou kunnen gebruiken, zou u agressieve beperking moeten implementeren om te blijven uw gebruikersinterface reageert. Dit zou resulteren in een langere vertraging voordat een succesvolle detectie plaatsvindt. Web Workers worden ondersteund in alle moderne browsers en zorgen voor een aanzienlijke prestatieverbetering van deze oplossing, waardoor scans in een fractie van een seconde onder optimale lichtomstandigheden mogelijk zijn.