vue2(vue3也可以使用)移动端h5网页实现扫一扫功能

一、效果

可以看调起了我们的摄像头,点击允许过后就打开了扫码界面

二、实现过程 

 1.安装包

@zxing/library

 2.构建页面

<template>
  <div class="scan">
    <div class="video-container">
      <div class="scan-box"></div>
      <video class="video" id="video-1"></video>
    </div>
    <!-- <div class="camera-container" v-if="videoInputDevices.length">
      <label>摄像头:</label>
      <select v-model="currentVideoInputDevice">
        <option
          v-for="(videoInputDevice, index) in videoInputDevices"
          :key="index"
          :value="videoInputDevice"
        >
          {{ videoInputDevice.label=='Video device 2'?'后置摄像头':'前置摄像头' }}
        </option>
      </select>
    </div> -->
    <!-- <div class="scan-animation">
      <div class="scan-line"></div>
      <div class="scan-box"></div>
    </div> -->
  </div>
</template>

<script>
import {
  BrowserMultiFormatReader,
  ChecksumException,
  FormatException,
} from "@zxing/library";
export default {
  name: "Scan",
  data() {
    return {
      codeReader: new BrowserMultiFormatReader(),
      videoInputDevices: [],
      currentVideoInputDevice: {},
      decodeResult: undefined,
    };
  },
  methods: {
    async openScan() {
      const _this = this;
      _this.codeReader
        .getVideoInputDevices() //老版本listVideoInputDevices()
        .then((videoInputDevices) => {
          if (videoInputDevices && videoInputDevices.length) {
            if (videoInputDevices.length > 1) {
              videoInputDevices.reverse();
            } //防止先唤出前摄像头
            _this.videoInputDevices = videoInputDevices;
            _this.currentVideoInputDevice = videoInputDevices[0];
          }
        })
        .catch(() => {});
    },

    decodeFromInputVideo() {
      const _this = this;
      _this.codeReader.reset();
      // 多次
      _this.codeReader.decodeFromVideoDevice(
        _this.currentVideoInputDevice.deviceId,
        "video-1",
        (result, err) => {
          if (result) {
            _this.decodeResult = result;
          }
          if (err) {
            if (err instanceof ChecksumException) {
              alert(1);
              console.log(
                "A code was found, but it's read value was not valid."
              );
            }
            if (err instanceof FormatException) {
              alert(2);
              console.log("A code was found, but it was in a invalid format.");
            }
          }
        }
      );
    },

    successDecode() {
      const _this = this;
      alert(_this.decodeResult.text);
    },
  },
  watch: {
    currentVideoInputDevice: function () {
      this.decodeFromInputVideo();
    },
    decodeResult: function () {
      this.successDecode();
    },
  },
  mounted: function () {
    this.openScan();
  },
  unmounted: function () {
    this.codeReader.reset(); //关闭摄像头
  },
};
</script>
<style scoped lang="scss">
.scan {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  overflow: hidden;
  background-color: #000;
  color: #fff;
}

// .video-container {
//   margin-bottom: 20px;
// }

.video {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
  // border: 2px solid #ff9900;
  border-radius: 10px;
  // box-shadow: 0 0 10px rgba(255, 153, 0, 0.5);
}

.camera-container {
  display: flex;
  align-items: center;
}

label {
  margin-right: 10px;
}

select {
  padding: 8px;
  border: 2px solid #ff9900;
  border-radius: 5px;
  background-color: transparent;
  color: #ff9900;
}

.scan-animation {
  position: relative;
  width: 200px;
  height: 200px;
  margin-top: 20px;
  // border: 2px solid #ff9900;
}

.scan-box {
  position: absolute;
  top: 0;
  left: 16%;
  width: 70%;
  height: 2px;
  box-sizing: border-box;
  background: linear-gradient(
    to left,
    #0074d9 0%,
    #0074d9 20%,
    transparent 40%,
    transparent 60%,
    #0074d9 80%,
    #0074d9 100%
  );
  animation: scanBoxAnimation 2s infinite;
}

@keyframes scanBoxAnimation {
  0% {
    transform: translateY(15vh);
  }
  50% {
    transform: translateY(70vh);
  }
  100% {
    transform: translateY(15vh);
  }
}
</style>

3.vite.config.js配置

https: true

注意

 如果使用的是vite创建的项目,单纯的配置一哈是打不开页面的,需要配置证书

可以参考vite集成https,并安装本地自签名证书 (同时解决msw fallback mode问题) - 知乎 (zhihu.com)

 vite.config.js则根据需求改写,可以参考一哈

import { fileURLToPath, URL } from "node:url";

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import fs from "fs";
import path from "path";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    https: true,
    https: {
      cert: fs.readFileSync(path.join(__dirname, "keys/cert.crt")),
      key: fs.readFileSync(path.join(__dirname, "keys/cert.key")),
    },
  },
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

这样一个简单的扫一扫功能就实现了 

二维码

可以使用草料草料二维码生成器

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值