使用jsQR制作浏览器二维码阅读器【技术备忘】【小故事】

介绍

我是Meister Guild Co., Ltd.新事业部的兔子。在我们的新业务部门,我们的目标是推出新服务每天,我都会测试想法并创建原型。

这一次,我想创建一个可以在浏览器使用二维码阅读器,所以我使用了 jsQR。

什么是jsQR?

它是一个用javascript制作的二维码阅读库。官方网站演示页面

↓ 试用演示页面的图

如何使用

让我们做一些类似于官方 Demo 页面的东西。

1 使用jsQR.js的准备

DL 并将其包含在您的项目中。

在 HTML 中加载 jsQR.js。

索引.html
<script src="./jsQR.js"></script>
2 展示准备

・<video> 元素显示用于 QR 读取的相机视频・ <canvas> 元素基于 <video> 元素显示相机视频・<canvas> 元素用于在 QR 码周围显示红框准备

索引.html
<div id="wrapper">
    <video id="video" autoplay muted playsinline></video>
    <canvas id="camera-canvas"></canvas>
    <canvas id="rect-canvas"></canvas>
</div>

接下来我会解释,因为使用jsQR检测二维码时,视频元素不能作为输入源还有一个 <canvas> 元素用于显示相机图像。

我想覆盖这些 & 视频元素不必可见,所以我准备了 css 如下。

样式.css
#wrapper{
    position: relative;
}

#video{
    position: absolute;
    top: 0px;
    left: 0px;
    visibility: hidden;
}

#camera-canvas{
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 50;
}

#rect-canvas{
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 100;
}
3 显示摄像机图像 脚本.js
// Webカメラの起動
const video = document.getElementById('video');
let contentWidth;
let contentHeight;

const media = navigator.mediaDevices.getUserMedia({ audio: false, video: {width:640, height:480} })
   .then((stream) => {
      video.srcObject = stream;
      video.onloadeddata = () => {
         video.play();
         contentWidth = video.clientWidth;
         contentHeight = video.clientHeight;
         canvasUpdate(); // 次で記述
         checkImage(); // 次で記述
      }
   }).catch((e) => {
      console.log(e);
   });
脚本.js
// カメラ映像のキャンバス表示
const cvs = document.getElementById('camera-canvas');
const ctx = cvs.getContext('2d');
const canvasUpdate = () => {
   cvs.width = contentWidth;
   cvs.height = contentHeight;
   ctx.drawImage(video, 0, 0, contentWidth, contentHeight);
   requestAnimationFrame(canvasUpdate);
}
4 二维码检测 官方使用
const code = jsQR(imageData, width, height, options?);

if (code) {
  console.log("Found QR code", code);
}

二维码检测使用上面的代码。jsQR 方法的第一个参数是“图像数据”,所以我们准备了 <canvas> 元素。

脚本.js
// QRコードの検出
const rectCvs = document.getElementById('rect-canvas');
const rectCtx =  rectCvs.getContext('2d');
const checkImage = () => {
   // imageDataを作る
   const imageData = ctx.getImageData(0, 0, contentWidth, contentHeight);
   // jsQRに渡す
   const code = jsQR(imageData.data, contentWidth, contentHeight);

   // 検出結果に合わせて処理を実施
   if (code) {
      console.log("QRcodeが見つかりました", code);
      drawRect(code.location);
   } else {
      console.log("QRcodeが見つかりません…", code);
      rectCtx.clearRect(0, 0, contentWidth, contentHeight);
   }
   setTimeout(()=>{ checkImage() }, 500);
}
脚本.js
// 四辺形の描画
const drawRect = (location) => {
   rectCvs.width = contentWidth;
   rectCvs.height = contentHeight;
   drawLine(location.topLeftCorner, location.topRightCorner);
   drawLine(location.topRightCorner, location.bottomRightCorner);
   drawLine(location.bottomRightCorner, location.bottomLeftCorner);
   drawLine(location.bottomLeftCorner, location.topLeftCorner)
}

// 線の描画
const drawLine = (begin, end) => {
   rectCtx.lineWidth = 4;
   rectCtx.strokeStyle = "#F00";
   rectCtx.beginPath();
   rectCtx.moveTo(begin.x, begin.y);
   rectCtx.lineTo(end.x, end.y);
   rectCtx.stroke();
}

探测器现已完成!

5 获取二维码信息

我还将提取二维码的信息。

准备显示单元

索引.html
<span id="qr-msg">QRコード: 見つかりません</span>
样式.css
#qr-msg{
    position: absolute;
    top: 500px;
    left: 0px;
}
脚本.js
// QRコードの検出
const rectCvs = document.getElementById('rect-canvas');
const rectCtx =  rectCvs.getContext('2d');
const checkImage = () => {
   // imageDataを作る
   const imageData = ctx.getImageData(0, 0, contentWidth, contentHeight);
   // jsQRに渡す
   const code = jsQR(imageData.data, contentWidth, contentHeight);

   // 検出結果に合わせて処理を実施
   if (code) {
      console.log("QRcodeが見つかりました", code);
      drawRect(code.location);
+     document.getElementById('qr-msg').textContent = `QRコード:${code.data}`;
   } else {
      console.log("QRcodeが見つかりません…", code);
      rectCtx.clearRect(0, 0, contentWidth, contentHeight);
+     document.getElementById('qr-msg').textContent = `QRコード: 見つかりません`;
   }
   setTimeout(()=>{ checkImage() }, 500);
}

信息现已可用。

整个代码 索引.html 索引.html
<!DOCTYPE html>
<head>
    <title>QRコードのテスト</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
        <div id="wrapper">
            <video id="video" autoplay muted playsinline></video>
            <canvas id="camera-canvas"></canvas>
            <canvas id="rect-canvas"></canvas>
            <span id="qr-msg">QRコード: 見つかりません</span>
        </div>
    <script src="./jsQR.js"></script>
    <script src="./script.js"></script>
</body>
</html>
样式.css 样式.css
#wrapper{
    position: relative;
}

#video{
    position: absolute;
    top: 0px;
    left: 0px;
    visibility: hidden;
}

#camera-canvas{
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 50;
}

#rect-canvas{
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 100;
}

#qr-msg{
    position: absolute;
    top: 500px;
    left: 0px;
}
脚本.js 脚本.js
// Webカメラの起動
const video = document.getElementById('video');
let contentWidth;
let contentHeight;

const media = navigator.mediaDevices.getUserMedia({ audio: false, video: {width:640, height:480} })
   .then((stream) => {
      video.srcObject = stream;
      video.onloadeddata = () => {
         video.play();
         contentWidth = video.clientWidth;
         contentHeight = video.clientHeight;
         canvasUpdate();
         checkImage();
      }
   }).catch((e) => {
      console.log(e);
   });

// カメラ映像のキャンバス表示
const cvs = document.getElementById('camera-canvas');
const ctx = cvs.getContext('2d');
const canvasUpdate = () => {
   cvs.width = contentWidth;
   cvs.height = contentHeight;
   ctx.drawImage(video, 0, 0, contentWidth, contentHeight);
   requestAnimationFrame(canvasUpdate);
}

// QRコードの検出
const rectCvs = document.getElementById('rect-canvas');
const rectCtx =  rectCvs.getContext('2d');
const checkImage = () => {
   // imageDataを作る
   const imageData = ctx.getImageData(0, 0, contentWidth, contentHeight);
   // jsQRに渡す
   const code = jsQR(imageData.data, contentWidth, contentHeight);

   // 検出結果に合わせて処理を実施
   if (code) {
      console.log("QRcodeが見つかりました", code);
      drawRect(code.location);
      document.getElementById('qr-msg').textContent = `QRコード:${code.data}`;
   } else {
      console.log("QRcodeが見つかりません…", code);
      rectCtx.clearRect(0, 0, contentWidth, contentHeight);
      document.getElementById('qr-msg').textContent = `QRコード: 見つかりません`;
   }
   setTimeout(()=>{ checkImage() }, 500);
}

// 四辺形の描画
const drawRect = (location) => {
   rectCvs.width = contentWidth;
   rectCvs.height = contentHeight;
   drawLine(location.topLeftCorner, location.topRightCorner);
   drawLine(location.topRightCorner, location.bottomRightCorner);
   drawLine(location.bottomRightCorner, location.bottomLeftCorner);
   drawLine(location.bottomLeftCorner, location.topLeftCorner)
}

// 線の描画
const drawLine = (begin, end) => {
   rectCtx.lineWidth = 4;
   rectCtx.strokeStyle = "#F00";
   rectCtx.beginPath();
   rectCtx.moveTo(begin.x, begin.y);
   rectCtx.lineTo(end.x, end.y);
   rectCtx.stroke();
}
奖金

我想知道我是否可以用二维码玩一些东西。我制作了一个程序,可以发出 do-re-mi-fa-so-ra-shi-do 的声音。创建一个从“C4”到“C5”的二维码并按住它发出声音。

脚本.js
   // 検出結果に合わせて処理を実施
   if (code) {
      console.log("QRcodeが見つかりました", code);
      drawRect(code.location);
      document.getElementById('my-qr-msg').textContent = `QRコード:${code.data}`;
+     playPitche(code.data);
   } 
脚本.js
+// 指定周波数音を出す
+let audioCtx = new AudioContext();
+const playMelody = (hz) => {
+    let osc = audioCtx.createOscillator();
+    osc.frequency.value = hz;
+    let audDes = audioCtx.destination;
+    osc.connect(audDes);
+    osc.start = osc.start || osc.noteOn;
+    osc.start();
+    setTimeout(function() { osc.stop(0);}, 200);
+}

+// ドレミファソラシドを鳴らす
+const playPitche = (name) => {
+    switch(name){
+        case 'C4':
+            playMelody(261);
+            break;
+        case 'D4':
+            playMelody(294);
+            break;
+        case 'E4':
+            playMelody(330);
+            break;
+        case 'F4':
+            playMelody(349);
+            break;
+        case 'G4':
+            playMelody(392);
+            break;
+        case 'A4':
+            playMelody(440);
+            break;
+        case 'B4':
+            playMelody(494);
+            break;
+        case 'C5':
+            playMelody(522);
+            break;
+    }
+}

原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308631502.html

59人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册