当前位置:首页 > 百科 > jquery调用手机摄像头扫描二维码 正文

jquery调用手机摄像头扫描二维码

来源:烟消火灭网   作者:娱乐   时间:2026-10-17 05:54:14

用 jQuery 直接调手机摄像头扫二维码,调用这事本身有个坑:jQuery 没有访问摄像头的手机摄像 API。它只是头扫个 DOM 操作库,getUserMedia 是描维码浏览器原生能力,跟 jQuery 没半毛钱关系。调用所以真实做法是手机摄像——用 jQuery 管界面和事件,用原生 JS 调摄像头,头扫再配一个解码库把视频流里的描维码二维码读出来。

我去年做过一个签到页,调用前端就是手机摄像 jQuery 写的。当时试过几个方案,头扫最后跑通的描维码是 getUserMedia + jsQR 这套组合。jsQR 体积小,调用纯 JS 解码,手机摄像不依赖 WebAssembly,头扫兼容性够用。

先拿到摄像头视频流

核心代码就几行,但有个前提:必须跑在 HTTPS 下,或者 localhost。HTTP 页面调 getUserMedia 会被浏览器直接拒绝,这个坑我踩过,调试半天以为是代码问题。

navigator.mediaDevices.getUserMedia({  video: {  facingMode: "environment" } }) .then(function(stream) {  $('#video')[0].srcObject = stream; $('#video')[0].play(); requestAnimationFrame(tick); }) .catch(function(err) {  $('#tip').text('摄像头打开失败:' + err.message); });

facingMode: "environment" 这行很关键,不加的话手机默认调前置摄像头,扫二维码得把手机翻过来对着自己,体验很蠢。桌面浏览器一般只有一颗摄像头,这个参数会被忽略,不影响。

用 canvas 抓帧,喂给解码器

视频流有了,接下来要不断从 <video> 里截图,画到 canvas 上,再把像素数据交给 jsQR 解析。这里用 requestAnimationFrame 循环,比 setInterval 更顺滑,也不会在页面切到后台时白白空转。

function tick() {  var video = $('#video')[0]; var canvas = $('#canvas')[0]; var ctx = canvas.getContext('2d'); if (video.readyState === video.HAVE_ENOUGH_DATA) {  canvas.width = video.videoWidth; canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0, canvas.width, canvas.height); var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var code = jsQR(imageData.data, imageData.width, imageData.height); if (code) {  $('#result').text('扫到了:' + code.data); // 停掉摄像头,避免一直占着 video.srcObject.getTracks().forEach(t => t.stop()); return; } } requestAnimationFrame(tick); }

注意 getImageData 这步,canvas 尺寸别设太大。我一开始直接用了视频原始分辨率 1920×1080,每帧都要复制几百万像素,中低端安卓机上直接卡成幻灯片。后来把 canvas 缩到 640 宽,解码成功率没降多少,帧率立刻上来了。

几个实际会遇到的麻烦

iOS Safari 要求 video 标签必须加 playsinline 属性,否则视频会强制全屏播放,页面上的扫描框、提示文字全被盖住。这个属性在安卓上加了也没副作用,建议无脑写上。

另外摄像头权限一旦被用户拒绝,再调 getUserMedia 不会重新弹窗,得引导用户去浏览器设置里手动开。我当时的做法是在 catch 里显示一段图文说明,告诉用户点地址栏左边的锁图标改权限,比干巴巴一句"请授权"有用得多。

还有个细节:页面切到后台再切回来,视频流有时候会断。visibilitychange 事件里重新调一次 getUserMedia 比较稳妥。jQuery 绑这个事件很简单:$(document).on('visibilitychange', ...)。

jQuery 在这套流程里到底干了什么

说白了就是三件事:选元素、改文字、绑事件。$('#video')、$('#tip').text()、$('#btn').on('click', startScan)。如果你项目里本来就引入了 jQuery,这么写没问题;如果只是为扫个二维码,用原生 document.getElementById 也完全够,没必要为此多加载 30KB 的库。

我个人的判断是:jQuery 调摄像头扫二维码这个说法本身不太准确,准确说法应该是"用浏览器原生 API 调摄像头,用 jQuery 做界面控制,用 jsQR 做解码"。三者各司其职,硬把功劳算在 jQuery 头上,容易让新手误以为 jQuery 有什么隐藏的摄像头接口,绕弯路。

标签:

责任编辑:百科