最近做项目时,要用到扫一扫二维码的功能,在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来保存。
改成这样新生成一个webview方法后,我自己测试了N遍,没遇到过那些问题了,我也用我同事的手机测试过,也没有问题。但愿是解决了吧 |