記錄vue用 html5+做移動APP 用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來保存。

改成這樣新生成一個webview方法后,我自己測試了N遍,沒遇到過那些問題了,我也用我同事的手機測試過,也沒有問題。但願是解決了吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM