首先声明下本篇文章并没有彻底解决h5纯网页扫码问题,这里只是将我的研究过程,以及搜集到的有用资料记录下,以抛砖引玉,一来给后来人以参考,二来也为我以后继续研究做个记录,省的每次都从头开始研究。
h5网页扫码实现起来比较困难,在微信中我们可以借助微信的api,实际很多都是微信做的工作。但是单纯的移动浏览器中呢?我之前探索过多次都是无果,网上也查阅了很多资料,并不是那么顺利。很多人都是退而求其次采用拍照上传的方法,也就是使用input type=file,但是采用这个方案的话要完成识别过程得经过1.点击按钮调用拍照 2.点击拍照按钮(一般手机拍照中间有个圆形的按钮) 3.确认图片上传(拍完了右下角有个√的图标),这三步,实际客户可能没对好焦就上传或者距离不合适,这样就得重新执行这三步,导致客户体验非常不好。如果能像原生app那样,直接一点就自动识别就好了,可是现在的浏览器厂家几乎没有任何一家对接h5扫二维码功能,追根溯源应该是还没纳入HTML标准吧,如果都像微信那样提供一个调用扫码的接口就好了,造福广大程序员。废话不多说了,下面记录我已经探索到的资料。
之前看某个案例使用的调用摄像头不停的在canvas上绘图,然后后台差不多每秒向后台上传一个图片,直到识别出结果停止,这样比较接近于原生,但是由于兼容性问题,比如qq内置浏览器,微信内置浏览器经常会失常,在手机自带浏览器或者uc等浏览器表现也是时好时坏。不过这样的逻辑应该是可以的。就是不停的从摄像头获取数据绘制到canvas上,同时每隔1秒向后台上传一次图,直到识别完成。
后来看到草料网上的效果实现得很不错,可惜是调用前置摄像头的,不知道只能前置还是可以设置的,大家可以用手机访问草料二维码解码器来测试。
确实可行,如果能调用后置就完美了。通过查看元素,发现是用的video标签显示摄像头数据的。至于到底是只能前置还是说前置后置可以选择呢?根据对草料网的代码分析,发现这么个关键性的js文件:static.clewm.net/static/js/p…
但是无法继续,里面还调用了其他的文件,不知道如何追踪。
function ajaxFileUploaddeqr() { $("#deqr_result").hide(), $(".deqr_prompt").hide(), $(".deqr_loading").show(), seajs.use(["lib/plug/ajaxfileupload", "uploadfile/uploaddeqr"], function(e, t) { t.ajaxFileUpload() }) } function checkURL(e) { var t = e, n = /http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=]*)?/, a = new RegExp(n); return 1 == a.test(t) ? !0 : !1 } var oldIE; $(function() { function e() { n.onScan = function(e, t) { var a = ""; if (!e) if ("onlineScan" === t.type && 1 === t.data.status) { var a = t.data.info.data[0]; n.stopScan(!1), $(".scanner").hide(), $("#scan-content").show().text(a), $("#continueToScan").show(), $("#copyResultBtn").show(), $("#htmlScanModal .modal-footer").show() } else if ("webScan" === t.type && t.data) { var a = t.data.data; n.stopScan(!1), $(".scanner").hide(), $("#scan-content").show().text(a), $("#continueToScan").show(), $("#copyResultBtn").show(), $("#htmlScanModal .modal-footer").show() } }, n.scan(document.querySelector("#scanVideo")), $(".scanner").show(), $("#continueToScan").hide(), $("#scan-content").hide(), $("#copyResultBtn").hide(), $("#htmlScanModal").modal("show"), $("#htmlScanModal .modal-footer").hide() } $("html").is(".lt-ie9") && (oldIE = !0), oldIE && $('input[type="text"], textarea').placeholder(); var t = document.documentElement.clientHeight - 70 - 360; $("#warper").css("min-height", t + "px"), $(document).click(function(e) { $(".deqr_url").is(e.target) || $(".deqr_url").has(e.target).length > 0 || "" != $("#deqr_urls").val() ? ($("#deqr_url_show").removeClass("none"), $("#qr-url").hide()) : ($("#deqr_url_show").addClass("none"), $("#qr-url").show()) }), $("#deqr_url_btn").click(function() { var e = $("#deqr_urls").val(); e.indexOf("http://") < 0 && e.indexOf("https://") < 0 && $("#deqr_urls").val("http://" + e), $("#deqr_result").hide(), $(".deqr_prompt").hide(), $("#modal-alert-deqr-result").modal("show"), $(".deqr_loading").show(); var e = $("#deqr_urls").val(); $.post("/Api/Browser/deqr", { data: e }, function(e) { 1 == e.status ? ($(".deqr_loading").hide(), $("p#deqrresult").text(e.data.RawData), $("#deqr_result").show()) : ($(".deqr_loading").hide(), alert(e.data.info), $(".deqr_prompt").show()) }, "json") }); var n = null; $("#toggleToFlash").click(function() { $("#htmlScanModal").modal("hide"), n.stopScan(!1), seajs.use("m/deqrCamera", function(e) { e.openCamera() }) }), $("#stopScan").click(function() { $("#htmlScanModal").modal("hide") }), $("#copyResultBtn").click(function() { if (!window.getSelection || !document.createRange) return void alert("您的浏览器不支持复制功能"); var e = window.getSelection(); e.removeAllRanges(); var t = document.createRange(); t.selectNodeContents($("#scan-content")[0]), e.addRange(t), document.execCommand("copy"), alert("复制成功") }), $("#continueToScan").click(function() { e() }), $("#htmlScanModal").on("hide.bs.modal", function() { setTimeout(function() { n.stopScan(!1) }, 300) }), $("#deqrcamera").click(function() { try { if (n = new $QRCodeScanner, n.canIUse()) return n.openWebScan = !0, n.scanFrequency = 1e3, void e(); throw Error("Can not use cam to scan.") } catch(t) { seajs.use("m/deqrCamera", function(e) { e.openCamera() }) } }), $("input#filedatacode").click(function() { var e = $(this).attr("uptype"); seajs.use(["//static.clewm.net/public/upload.js?v=20170503", "m/upload"], function(t, n) { n.upload(e) }) }) });
带着这个问题继续搜索,一个网友提供了这个链接:
ZXing | Scan QR Code from Video Camera
虽然里面写的能选择前置和后置,但是经过测试发现还是只能调用前置摄像头。
两个手机都是如此,均不能调用后置摄像头。不知道怎么回事,问题暂时调查到这儿。
参考文章:www.cnblogs.com/yisuowushin…
补充目前看到的已经实现或半实现的:
1.打开速度极慢,要耐心等待。很久之前看到的。识别准确率不太好。
2.无效。普通浏览器会花屏无法正常录像,在微信环境下完全无效果
3.效果很棒。只是默认调用的前置摄像头。在微信下也可以使用。目前看到的实现最好的一款。