h5实现扫码功能

547 阅读2分钟

项目环境介绍

vue-cli3搭建的vue2项目

vue-qrcode-reader资料相关

源码地址: github.com/gruhn/vue-q…

使用文档:vue-qrcode-reader.netlify.app/

包含三个方法QrcodeStream, QrcodeDropZone, QrcodeCapture;我们只用到有三个方法QrcodeStream

1、QrcodeStream:

用法:打开相机,显示视频流并实时扫描二维码。

Events
事件名触发
detect加载了相机视频流,持续扫码二维码,解析二维码
formats(v5.3启用)拿到条形码格式
camera-on(v5.0启用)相机开始传输数据
camera-off(v5.0启用)相机关闭
error(v5.0启用)启动摄像头失败
decode(v5.0删除,用detect替代)
init(v5.0删除,用camera-on/error替代)
camera(v5.0删除,用constraints替代)
Props
名称属性说明
pausedBoolean暂停相机
trackFunction突出检测到的二维码
constraintsMediaTrackConstraints配置相机参数
torchBoolean开启手电筒
(MediaTrackConstraints)相机参数说明
参数描述举例
width视频流的宽度限制
height视频流的高度限制
aspectRatio视频流的宽高比限制
frameRate视频流的帧率限制
facingMode摄像头设备的朝向模式限制,例如前置或后置摄像头'user'(前置摄像头),'environment'(后置摄像头)或 'left''right'(双摄像头设备)
resizeMode视频流的调整模式限制,用于控制如何调整视频以适应指定的宽高比'none'(不调整)、'crop-and-scale'(裁剪和缩放)或 'scale-down'(缩小至限制范围)
sampleRate音频流的采样率限制
sampleSize音频流的采样大小限制
echoCancellation是否启用回声消除功能的限制
autoGainControl是否启用自动增益控制功能的限制
noiseSuppression是否启用噪声抑制功能的限制
latency音频流的延迟限制
channelCount音频流的通道数限制
deviceId指定使用的设备的 ID,用于选择特定的摄像头或麦克风设备
groupId指定设备组的 ID,用于关联相关设备,例如同时选择前后摄像头的设备组

2、QrcodeDropZone:

用法:将包含二维码的图像文件拖放到该区域中进行扫描

3、QrcodeCapture:

用法:上传一张图片,解析其中二维码

在vue2项目中引用 vue-qrcode-reader

注意一定要按照低版本的

npm install vue-qrcode-reader@3

扫码页面开发

<template>
    <div style="height: 100%">
      <qrcode-stream
          v-show="qrcode"
          :camera="camera"
          :torch="torchActive"
          @decode="onDecode"
          @init="onInit"
      >
          <div>
              <div class="qr-scanner">
                  <div class="box">
                      <div class="line"></div>
                      <div class="angle"></div>
                  </div>
                  <div class="txt">
                      请对准二维码
                  </div>
              </div>
          </div>
      </qrcode-stream>
  </div>
</template>

<script>
import { QrcodeStream } from 'vue-qrcode-reader'
export default {
  components: {
    QrcodeStream
  },
  data() {
    return {
      error: '',
      qrcode: true,
      torchActive: false, // 手电筒
      camera: 'rear'// front, rear, auto, off,
    }
  },
  methods: {
    onDecode(result) {
      this.$emit('success', result)
    },
    async onInit(promise) {
      try {
        await promise
      } catch (error) {
        if (error.name === 'NotAllowedError') {
          this.error = '您需要授予相机访问权限'
        } else if (error.name === 'NotFoundError') {
          this.error = '这个设备上没有摄像头'
        } else if (error.name === 'NotSupportedError') {
          this.error = '所需的安全上下文(HTTPS、本地主机)'
        } else if (error.name === 'NotReadableError') {
          this.error = '相机被占用'
        } else if (error.name === 'OverconstrainedError') {
          this.error = '安装摄像头不合适'
        } else if (error.name === 'StreamApiNotSupportedError') {
          this.error = '此浏览器不支持流API'
        }
        this.$toast(this.error)
      }
    },
    closeCamera() { // 关闭摄像头
      this.qrcode = false
      this.camera = 'off'
    },
    openFlash() { // 打开手电
      switch (this.torchActive) {
        case true:
          this.torchActive = false
          break
        case false:
          this.torchActive = true
          break
      }
    }
  },
}
</script>

<style lang="less" scoped>
.cameraMessage {
  width: 100%;
  height: 100%;
}
.qr-scanner {
  background-size: 3rem 6rem;
  background-position: -1rem -1rem;
  width: 100%;
  height: 700px;
  position: relative;
  background-color: transparent;
  opacity: 0.8
}
.qr-scanner .box {
  width: 213px;
  height: 213px;
  position: absolute;
  left: 50%;
  top: 20%;
  transform: translate(-50%, 0);
  overflow: hidden;
  border: 0.1rem solid rgba(0, 255, 51, 0.2);
  background-color: transparent;
}
.qr-scanner .txt {
  width: 100%;
  height: 35px;
  line-height: 35px;
  font-size: 14px;
  text-align: center;
  margin: 0 auto;
  position: absolute;
  top: 60%;
  left: 0;
  color: white
}
.qr-scanner .myQrcode {
  text-align: center;
  color: #00ae10;
}
.qr-scanner .line {
  height: calc(100% - 2px);
  width: 100%;
  background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%);
  border-bottom: 3px solid #00ff33;
  transform: translateY(-100%);
  animation: radar-beam 2s infinite alternate;
  animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
  animation-delay: 1.4s;
}

.qr-scanner .box:after,
.qr-scanner .box:before,
.qr-scanner .angle:after,
.qr-scanner .angle:before {
  content: '';
  display: block;
  position: absolute;
  width: 3vw;
  height: 3vw;

  border: 0.2rem solid transparent;
}

.qr-scanner .box:after,
.qr-scanner .box:before {
  top: 0;
  border-top-color: #00ff33;
}

.qr-scanner .angle:after,
.qr-scanner .angle:before {
  bottom: 0;
  border-bottom-color: #00ff33;
}

.qr-scanner .box:before,
.qr-scanner .angle:before {
  left: 0;
  border-left-color: #00ff33;
}

.qr-scanner .box:after,
.qr-scanner .angle:after {
  right: 0;
  border-right-color: #00ff33;
}

@keyframes radar-beam {
  0% {
      transform: translateY(-100%);
  }

  100% {
      transform: translateY(0);
  }
}
</style>


<div class="g-content">
  <qrcode @success="scanResult"></qrcode >
  </div>
</template>

<script>
import qrcode from './components/qrReader.vue'
export default {
  name: 'scan',
  components: {
    qrcode
  },
  methods: {
    scanResult(text) {
    // 处理扫码结果
    }
  }
}
</script>

<style lang="less" scoped>
.g-content{
  height: 100%;
}
</style>

关于只能在https环境调试的问题

使用vue-cli3创建的项目

  devServer: {
    port: 8086,
    proxy: proxy,
    https: true
  }

本地运行项目,在手机打开

手机和电脑连同一个网,成功运行项目后,打开下面那个网址(本地ip地址开头的)

最后效果

33.jpg