最近做项目时,要用到扫一扫二维码的功能,在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遍,没遇到过那些问题了,我也用我同事的手机测试过,也没有问题。但愿是解决了吧