Tag: npm jsqr

  • A QR Code Scanner Component for Cordova in ReactJS that works on Android.

    Yes, a component that does the job well. Code below, customise for your use case.

    Note: It does not use the “cordova-plugin-qrscanner” which is broken at the time of writing.

    import React, { Component } from "react";
    import jsQR from "jsqr";
    import $ from "jquery";
    
    class QrCodeScanner extends Component {
      constructor(props) {
        super(props);
        this.videoRef = React.createRef();
        this.state = {
          qrcode: "",
          videoError: false
        }
      }
    
      componentDidMount() {
        this.checkCameraPermissions();
      }
    
      componentWillUnmount() {
        this.stopScanner();
      }
    
      checkCameraPermissions = async () => {
        var thisController = this;
    
        cordova.plugins.permissions.requestPermission(
          cordova.plugins.permissions.CAMERA,
          function (status) {
            if (status.hasPermission) {
              console.log("Camera permission granted");
              thisController.startScanner();
            } else {
              console.log("Camera permission denied");
              thisController.state.videoError = true;
              thisController.setState(thisController.state);
            }
          },
          function () {
            console.log("Error requesting camera permission");
            thisController.state.videoError = true;
            thisController.setState(thisController.state);
          }
        );
      };
    
      startScanner = () => {
        navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })
          .then((stream) => {
            this.videoRef.current.srcObject = stream;
            this.videoRef.current.play();
            this.videoRef.current.addEventListener("loadedmetadata", this.scanFrame);
          })
          .catch((error) => {
            console.error("Error starting scanner: ", error);
            this.state.videoError = true;
          });
      };
    
      stopScanner = () => {
        const stream = this.videoRef.current.srcObject;
        if (stream) {
          const tracks = stream.getTracks();
          tracks.forEach((track) => {
            track.stop();
          });
        }
        document.getElementById("qrScannerPreview").pause();
      };
    
      scanFrame = () => {
        var thisController = this;
        const canvas = document.createElement("canvas");
        const context = canvas.getContext("2d");
        const video = this.videoRef.current;
    
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
    
        const code = jsQR(imageData.data, imageData.width, imageData.height);
        if (code) {
          console.log("QR code detected: ", code.data);
          //Do something with the extracted code.
    
            return;
          }
    
        }
    
        requestAnimationFrame(this.scanFrame);
      };
    
    
      render() {
    
        return (
          <div style={{ height: "90vh", marginTop: "7vh" }} >
    
            <div id="view-qrscanner" >
              <div>
                <div className="container-qr">
                  <div style={{ paddingTop: "1vh" }} >
                    <div align="center">
                      <h3 style={{ fontWeight: 'bold', fontSize: "1.28rem", color: 'white' }}>Scan your onboarding QR code</h3>
                      <label style={{ padding: "10vw", fontSize: "0.92rem", color: 'white' }}>Postion the QR Code a few inches away</label>
                    </div>
                    <div id="camera" className="pre_capture_frame" style={{ width: '95vw' }} />
                    {!this.state.videoError && <video style={{ width: "85vw", height: "85vw", margin: '4.5vw', borderRadius: '12px' }}
                      ref={this.videoRef} id="qrScannerPreview" />}
                    {this.state.videoError && <div>Could not start the video source.
                      Please ensure that you have granted camera permissions and that 
                      the camera is not being used by another app.</div>}
                    <br />
                    <div id="tick" align="center" style={{ display: 'none', color: '#94bde9',
                                                         fontSize: '108px', width: '95vw' }}>
                      &#10004;
                    </div>
                  </div>
    
                </div>
              </div>
            </div>
    
          </div>
        );
      }
    }
    
    export default QrCodeScanner;