cozmo / jsQR

A pure javascript QR code reading library. This library takes in raw images and will locate, extract and parse any QR code found within.
https://cozmo.github.io/jsQR/
Apache License 2.0
3.7k stars 607 forks source link

How to: Scan URL QR code and auto redirect to page #134

Closed jsa2233 closed 5 years ago

jsa2233 commented 5 years ago

I am trying to scan a URL QR code and allowing a quick action of redirecting the outputData to the the page. did anyone tried to try this use case ? if yes please assist, I tried Javascripts window.location but failed.

my partial code below :

--------
  <div id="loadingMessage">🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>
  <canvas id="canvas" hidden></canvas>
  <div id="output" hidden>
    <div id="outputMessage">No QR code detected.</div>
    <div hidden><b>Data:</b><a target="_self" href="#outputData" id="outputData"></a></div>
  </div>
  <script>
    var video = document.createElement("video");
    var canvasElement = document.getElementById("canvas");
    var canvas = canvasElement.getContext("2d");
    var loadingMessage = document.getElementById("loadingMessage");
    var outputContainer = document.getElementById("output");
    var outputMessage = document.getElementById("outputMessage");
    var outputData = document.getElementById("outputData");

    function drawLine(begin, end, color) {
      canvas.beginPath();
      canvas.moveTo(begin.x, begin.y);
      canvas.lineTo(end.x, end.y);
      canvas.lineWidth = 4;
      canvas.strokeStyle = color;
      canvas.stroke();
    }

    // Use facingMode: environment to attemt to get the front camera on phones
    navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
      video.srcObject = stream;
      video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
      video.play();
      requestAnimationFrame(tick);
    });

    function tick() {
      loadingMessage.innerText = "⌛ Loading video..."
      if (video.readyState === video.HAVE_ENOUGH_DATA) {
        loadingMessage.hidden = true;
        canvasElement.hidden = false;
        outputContainer.hidden = false;

        canvasElement.height = video.videoHeight;
        canvasElement.width = video.videoWidth;
        canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
        var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
        var code = jsQR(imageData.data, imageData.width, imageData.height, {
          inversionAttempts: "dontInvert",
        });
        if (code) {
          drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
          drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
          drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
          drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
          outputMessage.hidden = true;
          outputData.parentElement.hidden = false;
          outputData.innerText = code.data;
        } else {
          outputMessage.hidden = false;
          outputData.parentElement.hidden = true;
        }
      }
      requestAnimationFrame(tick);
    }
  </script>
</body>
</html>
------
innovaciones commented 5 years ago

The string URL would be code.data so you could try adding a function like:

function getURL(result) { window.setTimeout(function () { location.href = result;}, 500); }

and then calling it with:

if (code) { drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58"); drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58"); drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58"); drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58"); getURL(code.data);

jsa2233 commented 5 years ago

The string URL would be code.data so you could try adding a function like:

function getURL(result) { window.setTimeout(function () { location.href = result;}, 500); }

and then calling it with:

if (code) { drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58"); drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58"); drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58"); drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58"); getURL(code.data);

Thanks a lot for your support @innovaciones ... I also Added outputData.setTimeout(check, 300); because it will keep scanning for new output resulting in a alot of requests during the scanning of the Barcode

innovaciones commented 5 years ago

Sure no problem, also you could add this code to only call the getURL function once:

function getURL(result) {
  // call only once
  getURL = function(){};
  window.setTimeout(function () { location.href = result;}, 500);
};
cozmo commented 5 years ago

Closing this issue as it seems like you got a good base to build off @jsa2233 - Feel free to comment or re-open if that's not the case. In general what @innovaciones said is correct though - you'd want to take the output of the scan and then send the user there, and I agree it makes sense to stop scanning once you have a successful scan.