经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
前端黑科技:使用 JavaScript 实现网页扫码功能
来源:cnblogs  作者:geekcjj  时间:2024/8/19 17:03:35  对本文有异议

在数字化时代,二维码已经渗透到我们生活的方方面面。从移动支付到产品溯源,二维码凭借其便捷性和高效性,成为了信息传递的重要载体。而随着前端技术的不断发展,我们甚至可以使用 JavaScript 在网页端实现二维码扫描功能,为用户提供更加便捷的操作体验。

本文将带您深入了解如何使用 JavaScript 调用摄像头,结合 jsQR 库,以及如何控制闪光灯,最终实现一个功能完善的网页扫码应用。

一、 项目概述

我们将创建一个简单的网页应用,该应用能够:

  1. 调用设备摄像头,获取实时视频流。
  2. 在网页上创建一个扫描区域,用户可以将二维码放置在该区域内进行扫描。
  3. 使用 jsQR 库解码扫描区域内的二维码图像数据,获取二维码内容。
  4. 提供手动输入二维码内容的功能。
  5. 如果设备支持,还可以控制闪光灯的开关,以便在光线不足的情况下进行扫描。

二、 实现步骤

1. HTML 结构

首先,我们需要构建基本的 HTML 结构,包括:

  • <video> 标签:用于展示摄像头捕获的实时视频流。
  • <canvas> 标签:用于绘制视频帧和扫描区域,并从中获取图像数据。
  • <div> 标签:用于创建扫描区域、按钮组等 UI 元素。
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>扫一扫</title>
  7. <link rel="stylesheet" href="style.css">
  8. </head>
  9. <body>
  10. <video id="video" autoplay></video>
  11. <canvas id="overlay" hidden></canvas>
  12. <div class="scan-area"></div>
  13. <div class="btn-group">
  14. <button id="manualInputBtn">手动输入</button>
  15. <button id="flashBtn">闪光灯</button>
  16. </div>
  17. <script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
  18. <script src="script.js"></script>
  19. </body>
  20. </html>

2. CSS 样式

为了提升用户体验,我们需要为页面元素添加一些样式:

  1. /* style.css */
  2. body {
  3. margin: 0;
  4. overflow: hidden;
  5. }
  6. #video {
  7. width: 100%;
  8. height: auto;
  9. display: block;
  10. }
  11. #overlay {
  12. position: absolute;
  13. top: 0;
  14. left: 0;
  15. width: 100%;
  16. height: 100%;
  17. pointer-events: none;
  18. }
  19. .scan-area {
  20. border: 3px solid yellow;
  21. position: absolute;
  22. top: 50%;
  23. left: 50%;
  24. transform: translate(-50%, -50%);
  25. width: 80%;
  26. height: 30%;
  27. }
  28. /* ...其他样式 */

3. JavaScript 交互

JavaScript 代码是实现扫码功能的核心部分,主要包括以下几个步骤:

  1. 获取摄像头权限: 使用 navigator.mediaDevices.getUserMedia() 方法请求访问用户的摄像头。

  2. 播放视频流: 将获取到的视频流赋值给 <video> 标签的 srcObject 属性,并调用 video.play() 方法开始播放。

  3. 创建扫描循环: 使用 requestAnimationFrame() 方法创建一个循环,不断地从视频流中获取帧图像,并进行二维码解码。

  4. 绘制视频帧: 在每一帧中,使用 canvas.drawImage() 方法将视频帧绘制到 <canvas> 元素上。

  5. 获取扫描区域图像数据: 使用 canvas.getImageData() 方法获取扫描区域的图像数据。

  6. 解码二维码: 使用 jsQR 库的 jsQR() 方法解码图像数据,如果解码成功,则获取二维码内容。

  7. 处理扫描结果: 对解码后的二维码内容进行处理,例如跳转到链接、显示信息等。

  8. 实现其他功能: 实现手动输入二维码内容和控制闪光灯等功能。

  1. // script.js
  2. const video = document.getElementById('video');
  3. const overlay = document.getElementById('overlay');
  4. const manualInputBtn = document.getElementById('manualInputBtn');
  5. const flashBtn = document.getElementById('flashBtn');
  6. const scanArea = document.querySelector('.scan-area');
  7. let stream;
  8. let scanning = false;
  9. let flashEnabled = false;
  10. // 获取摄像头权限并开始播放视频流
  11. navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })
  12. .then(s => {
  13. stream = s;
  14. video.srcObject = stream;
  15. video.play();
  16. // 开始扫描
  17. scanning = true;
  18. requestAnimationFrame(scan);
  19. })
  20. .catch(err => {
  21. console.error("无法访问摄像头:", err);
  22. });
  23. // 扫描二维码
  24. function scan() {
  25. if (scanning) {
  26. const canvas = overlay.getContext('2d');
  27. const videoWidth = video.videoWidth;
  28. const videoHeight = video.videoHeight;
  29. // 设置画布大小
  30. overlay.width = videoWidth;
  31. overlay.height = videoHeight;
  32. // 将视频帧绘制到画布上
  33. canvas.drawImage(video, 0, 0, videoWidth, videoHeight);
  34. // ...获取扫描区域图像数据
  35. // 使用 jsQR 库解码二维码
  36. const code = jsQR(imageData.data, imageData.width, imageData.height);
  37. // 如果成功解码,则停止扫描并处理结果
  38. if (code) {
  39. scanning = false;
  40. handleScanResult(code.data);
  41. } else {
  42. requestAnimationFrame(scan);
  43. }
  44. }
  45. }
  46. // 处理扫描结果
  47. function handleScanResult(data) {
  48. alert("扫描结果:" + data);
  49. // 这里可以根据扫描结果进行相应的操作,例如跳转到链接或显示信息
  50. }
  51. // 手动输入按钮点击事件
  52. manualInputBtn.addEventListener('click', function() {
  53. // ...
  54. });
  55. // 闪光灯按钮点击事件
  56. flashBtn.addEventListener('click', function() {
  57. // ...
  58. });

三、完整代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>扫一扫</title>
  7. <style>
  8. body {
  9. margin: 0;
  10. overflow: hidden;
  11. }
  12.  
  13. #video {
  14. width: 100%;
  15. height: auto;
  16. display: block;
  17. }
  18.  
  19. #overlay {
  20. position: absolute;
  21. top: 0;
  22. left: 0;
  23. width: 100%;
  24. height: 100%;
  25. pointer-events: none;
  26. }
  27.  
  28. .scan-area {
  29. border: 3px solid yellow;
  30. position: absolute;
  31. top: 50%;
  32. left: 50%;
  33. transform: translate(-50%, -50%);
  34. width: 80%;
  35. height: 30%;
  36. }
  37.  
  38. .btn-group {
  39. position: absolute;
  40. bottom: 20px;
  41. left: 50%;
  42. transform: translateX(-50%);
  43. display: flex;
  44. }
  45.  
  46. button {
  47. background-color: rgba(0, 0, 0, 0.5);
  48. color: white;
  49. border: none;
  50. padding: 10px 20px;
  51. margin: 0 10px;
  52. border-radius: 5px;
  53. font-size: 16px;
  54. cursor: pointer;
  55. }
  56. </style>
  57. </head>
  58. <body>
  59.  
  60. <video id="video" autoplay></video>
  61. <canvas id="overlay" hidden></canvas>
  62.  
  63. <div class="scan-area"></div>
  64.  
  65. <div class="btn-group">
  66. <button id="manualInputBtn">手动输入</button>
  67. <button id="flashBtn">闪光灯</button>
  68. </div>
  69.  
  70. <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
  71. <script>
  72. const video = document.getElementById('video');
  73. const overlay = document.getElementById('overlay');
  74. const manualInputBtn = document.getElementById('manualInputBtn');
  75. const flashBtn = document.getElementById('flashBtn');
  76. const scanArea = document.querySelector('.scan-area');
  77.  
  78. let stream;
  79. let scanning = false;
  80. let flashEnabled = false;
  81.  
  82. // 获取摄像头权限并开始播放视频流
  83. navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })
  84. .then(function(s) {
  85. stream = s;
  86. video.srcObject = stream;
  87. video.play();
  88.  
  89. // 开始扫描
  90. requestAnimationFrame(scan);
  91. })
  92. .catch(function(err) {
  93. console.error("无法访问摄像头:", err);
  94. });
  95.  
  96. // 扫描二维码
  97. function scan() {
  98. if (scanning) {
  99. const canvas = overlay.getContext('2d');
  100. const videoWidth = video.videoWidth;
  101. const videoHeight = video.videoHeight;
  102.  
  103. // 设置画布大小
  104. overlay.width = videoWidth;
  105. overlay.height = videoHeight;
  106.  
  107. // 将视频帧绘制到画布上
  108. canvas.drawImage(video, 0, 0, videoWidth, videoHeight);
  109.  
  110. // 获取扫描区域的坐标和尺寸
  111. const scanAreaRect = scanArea.getBoundingClientRect();
  112. const scanAreaX = scanAreaRect.left;
  113. const scanAreaY = scanAreaRect.top;
  114. const scanAreaWidth = scanAreaRect.width;
  115. const scanAreaHeight = scanAreaRect.height;
  116.  
  117. // 获取扫描区域的图像数据
  118. const imageData = canvas.getImageData(scanAreaX, scanAreaY, scanAreaWidth, scanAreaHeight);
  119.  
  120. // 使用 jsQR 库解码二维码
  121. const code = jsQR(imageData.data, imageData.width, imageData.height);
  122.  
  123. // 如果成功解码,则停止扫描并处理结果
  124. if (code) {
  125. scanning = false;
  126. handleScanResult(code.data);
  127. } else {
  128. requestAnimationFrame(scan);
  129. }
  130. }
  131. }
  132.  
  133. // 处理扫描结果
  134. function handleScanResult(data) {
  135. alert("扫描结果:" + data);
  136.  
  137. // 这里可以根据扫描结果进行相应的操作,例如跳转到链接或显示信息
  138. }
  139.  
  140. // 手动输入按钮点击事件
  141. manualInputBtn.addEventListener('click', function() {
  142. const input = prompt("请输入二维码内容:");
  143. if (input) {
  144. handleScanResult(input);
  145. }
  146. });
  147.  
  148. // 闪光灯按钮点击事件
  149. flashBtn.addEventListener('click', function() {
  150. if ('torch' in navigator.mediaDevices.getUserMedia({ video: true })) {
  151. flashEnabled = !flashEnabled;
  152. stream.getVideoTracks()[0].applyConstraints({
  153. advanced: [{ torch: flashEnabled }]
  154. });
  155.  
  156. // 更新按钮文本
  157. flashBtn.textContent = flashEnabled ? '关闭闪光灯' : '闪光灯';
  158. } else {
  159. alert('您的设备不支持闪光灯功能。');
  160. }
  161. });
  162.  
  163. // 开始扫描
  164. scanning = true;
  165. </script>
  166.  
  167. </body>
  168. </html> 

四、 总结

通过以上步骤,我们成功地使用 JavaScript 在网页端实现了二维码扫描功能。该功能可以广泛应用于各种场景,例如:

  • 移动支付: 用户可以使用手机扫描网页上的二维码完成支付。
  • 产品溯源: 用户可以扫描产品上的二维码,查看产品信息、生产日期、物流信息等。
  • 活动签到: 用户可以使用手机扫描二维码完成活动签到。

随着 Web 技术的不断发展,相信未来会有更多创新的应用场景出现。

希望本文能够帮助您了解网页扫码功能的实现原理,并激发您探索更多前端黑科技的兴趣。

原文链接:https://www.cnblogs.com/geekcjj/p/18352006

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号