记录vue用 html5+做移动APP 用barcode做扫一扫功能时安卓 的bug(黑屏、错位等等)和解决方法
程序员文章站
2022-03-22 14:27:14
最近做项目时,要用到扫一扫二维码的功能,在html5+里面有提供barcode功能,于是照过来用了, 写的代码如下 : 扫码页面: 去扫一扫前的页面: 两个页面运行的效果如下 当时以为很容易,结果做出后遇到各种BUG,有时黑屏,有时位置偏移,有时扫码框偏移等等 比如下图 这个扫码框已经偏移了 很奇怪 ......
最近做项目时,要用到扫一扫二维码的功能,在html5+里面有提供barcode功能,于是照过来用了,
写的代码如下 :
扫码页面:
<style lang="less" scoped> #camera { height: 100%; width: 100%; .van-icon { top: -2px; font-size: 30px; color: #fff; &.back { left: 10px; } &.light { right: 10px; } } #scan { width: 100%; height: 100%; z-index: 2; position: fixed; left: 0; top: 0; background: rgba(0, 0, 0, 1); } .tips { text-align: center; position: absolute; width: 100%; top: 40%; color: #fff; z-index: 3; left: 0%; } .action { position: fixed; z-index: 777; width: 100%; left: 0; bottom: 0; .items { display: flex; justify-content: space-around; background: rgba(0, 0, 0, 0.35); width: 60%; padding: 4px; margin: 4px auto; .item { flex-basis: 50px; text-align: center; img { width: 27px; } } } } } </style> <template> <div id="camera"> <div id="scan"></div> <div class="tips">"加载中...</div> <div class="action"> <div class="items"> <div class="item" @click="openlight" ><img src="../assets/img/png-60@3x.png"></div> <div class="item" @click="getpicture()" ><img src="../assets/img/png-59@3x.png"></div> <div class="item" @click="cancelscan()" ><img src="../assets/img/png-61@3x.png"></div> </div> </div> </div> </template> <script type='text/ecmascript-6'> let scan = null; export default { data() { return { codeurl: "", islight: false, showenter: false, extra: null, type: "" }; }, mounted() { if (window.plus) { let s = plus.navigator.checkpermission("camera"); if (s !== "notdeny") { plus.nativeui.alert("相机权限未获取,请往设置应用程序里面开启权限!"); } } this.startscan(); //`进入页面就调取扫一扫 }, beforedestroy() { if (!window.plus) return; scan.cancel(); scan.close(); }, methods: { // 打开闪光灯 openlight() { this.islight = !this.islight; scan.setflash(this.islight); }, //创建扫描控件 startrecognize() { let that = this; if (!window.plus) return; scan = null; scan = new plus.barcode.barcode( "scan", [plus.barcode.qr, plus.barcode.ean8, plus.barcode.ean13], { framecolor: "#1294cb", scanbarcolor: "#1294cb", top: "100px", left: "0px", width: "100%", height: "500px", position: "fixed" } ); scan.onmarked = onmarked; function onmarked(type, result, file) { result = result.replace(/\n/g, ""); that.storage.save("cameradata", result); that.codeurl = result; //扫描后返回值 that.$router.go(-1); } }, // //开始扫描 startscan() { if (!window.plus) return; this.startrecognize(); //创建控件 settimeout(() => { scan.start(); }, 200); }, // 取消扫描 cancelscan() { let l = plus.webview.all().length; this.$toast(l); if (l > 1) { let ws = plus.webview.currentwebview(); plus.webview.close(ws); } else { this.$router.go(-1); } // this.$router.go(-1); if (!window.plus) return; plus.navigator.setstatusbarstyle("dark"); if (scan) { scan.cancel(); //关闭扫描 scan.close(); //关闭条码识别控件 } }, getpicture() { plus.gallery.pick(src => { plus.barcode.scan( src, (type, result) => { scan.cancel(); //关闭扫描 scan.close(); this.storage.save("cameradata", result); this.$router.go(-1); }, error => { this.$toast({ position: "bottom", message: error.message }); } ); }); } } }; </script>
去扫一扫前的页面:
<template> <div id="workshop"> <div id="scan"> <div id="header" :style="{height:statubar}" > <div class="wrap" :style="{'padding-top':paddingtop}" > <div class="back"> <van-icon name="arrow-left" @click="$router.go(-1)" /> </div> <div class="title">扫一扫</div> <div class="history"> <span> 历史记录 </span> </div> </div> </div> <div class="searchbox"> <van-row> <van-col span="3"> <van-button size="large" :square="true" @click="gocamera" > <img class="right" src="../../assets/img/png-73@3x.png" /> </van-button> </van-col> <van-col span="21" class="van-hairline--surround" > <van-search v-model="value" :placeholder="pla" @keydown.stop="search" shape="round" > <span slot="left-icon"></span> </van-search> </van-col> </van-row> </div> </div> </div> </template> <script> export default { name: "orderscan", data() { return { result: {}, value: "", }; }, methods: { // 去扫码 gocamera() { this.$router.go("/camera") }, // 手动输入时搜索 search(e) { if (e.keycode == 13) { this.onsearch(); } }, // 搜索结果 onsearch() {} }, mounted() { let camera = sessionstorage.getitem("cameradata"); if (camera && camera != "null") { this.value = sessionstorage.getitem("cameradata"); sessionstorage.removeitem("cameradata"); } } }; </script>
两个页面运行的效果如下
当时以为很容易,结果做出后遇到各种bug,有时黑屏,有时位置偏移,有时扫码框偏移等等
比如下图 这个扫码框已经偏移了
很奇怪,看官方提供的app怎么扫都是没有问题。于是乎百度各种解决方法,看到 有的说是因为摄像头很耗资源,要用单独的webview来分配,用完即关,看看官方的案例,貌似确实也是新建一个webview来启动的。
心想应该就是这样吧,于是,把方法改了一下。去扫一扫前的页面的$router.go("/camera")时直接改成生成新一个webview,改后的js代码如下;
gocamera() { //新建一个webview来启动扫一扫,不再$router.push()的跳转 let h = location.href; let n = h.indexof("#"); let r = h.substr(n); h = h.replace(r, "#/camera"); let ws = plus.webview.create(h); ws.show(); },
在扫码页面,修改扫码成功后router.go(-1)改成关闭当前的webview,和设置一个定时器来加载摄像头的资源的js更改如下
let scan = null; export default { data() { return { codeurl: "", islight: false, showenter: false, extra: null, scan: null, type: "" }; }, mounted() { settimeout(() => { // 设置500毫秒等资源加载 if (window.plus) { let s = plus.navigator.checkpermission("camera"); if (s !== "notdeny") { plus.nativeui.alert("相机权限未获取,请往设置应用程序里面开启权限!");
return; } this.startscan(); //`进入页面就调取扫一扫 } }, 500); }, beforedestroy() { if (!window.plus) return; scan.cancel(); scan.close(); // scan = null; }, methods: { // 打开闪光灯 openlight() { this.islight = !this.islight; scan.setflash(this.islight); }, //创建扫描控件 startrecognize() { let that = this; if (!window.plus) return; scan = null; scan = new plus.barcode.barcode( "scan", [plus.barcode.qr, plus.barcode.ean8, plus.barcode.ean13], { framecolor: "#1294cb", scanbarcolor: "#1294cb", top: "100px", left: "0px", width: "100%", height: "500px", position: "fixed" } ); scan.onmarked = onmarked; function onmarked(type, result, file) { result = result.replace(/\n/g, ""); that.storage.save("cameradata", result); if (plus.webview.all().length > 1) { // 扫码成功后关闭当前的webview let ws = plus.webview.currentwebview(); plus.webview.close(ws); } } }, // //开始扫描 startscan() { if (!window.plus) return; this.startrecognize(); //创建控件 settimeout(() => { scan.start(); }, 200); }, // 取消扫描 cancelscan() { let l = plus.webview.all().length;if (l > 1) { let ws = plus.webview.currentwebview(); plus.webview.close(ws); } else { this.$router.go(-1); } // this.$router.go(-1); if (!window.plus) return; plus.navigator.setstatusbarstyle("dark"); if (scan) { scan.cancel(); //关闭扫描 scan.close(); //关闭条码识别控件 } }, // 从相册选择图片扫码 getpicture() { plus.gallery.pick(src => { plus.barcode.scan( src, (type, result) => { scan.cancel(); scan.close(); this.storage.save("cameradata", result); if (plus.webview.all().length > 1) { // 扫码成功后关闭当前的webview let ws = plus.webview.currentwebview(); plus.webview.close(ws); } }, error => { this.$toast({ position: "bottom", message: error.message }); } ); }); } } };
至于扫码成功的数据切换,我是用localstorage来保存,跳转去扫码页面前设置一个定时器检测key值,改成这样新生成一个webview后,我自己测试了n遍,没遇到过那些问题了,我也用我同事的手机测试过,也没有问题。但愿是解决了吧