首页 前端知识 vue3.0, vue2.0项目h5,pc端实现扫描二维码(qrcode-reader-vue3 , @zxing/library和vue-qrcode-reader)

vue3.0, vue2.0项目h5,pc端实现扫描二维码(qrcode-reader-vue3 , @zxing/library和vue-qrcode-reader)

2024-08-27 09:08:33 前端知识 前端哥 953 984 我要收藏

扫码二维码的方法

  1. 第一微信jssdk自带的扫一扫功能,
    • 优点:无兼容性问题,只要微信能扫一扫的场景,这个api都能扫。
    • 缺点:只能在微信环境使用,浏览器环境中不能使用,另外一点,需要后端配合出接口,获取当前公众号的appid等信息。
  2. 直接用原生插件实现,发现两种插件 vue-qrcode-reader 和 @zxing/library,两个插件都可以在项目中使用,

    vue-qrcode-reader在苹果手机中无法使用,第一次扫码无反应调不起摄像头,需要返回第二次进入才会正常(暂未找到解决方法),
    @zxing/library安卓ios都能正常调用起摄像头,但是对于华为手机,因为华为手机有6个摄像头,正常手机就2个摄像头,所以对于华为手机要兼容判断下
    如果二维码参数太多,生成的二维码密度就会越多,正常大小扫不出来,所以需要放大二维码,参数不能传太多,影响扫码准确性

    1. @zxing/library 和vue-qrcode-reade 库兼容问题
      在装有 iOS < 14.3 相机访问仅适用于本机 Safari,而不适用于其他浏览器 (Chrome,…) 或使用 UIWebView 或 WKWebView 的应用。这不是这个库的限制,而是苹果有限的 WebRTC 支持的限制,
      但是 iOS 14.3(2020 年 12 月发布)现在也支持第三方浏览器中的 WebRTC。
      浏览器层使用的是 MediaDevices Web API,这是旧版浏览器不支持的。
      您可以使用 WebRTC 适配器等外部 polyfill 来增加浏览器兼容性。
      该库使用的是 TypedArray 等,这在较旧的浏览器(例如 Android 4 默认浏览器)中不可用。
      Int32ArrayUint8ClampedArray您可以使用 core-js 添加对这些浏览器的支持

qrcode-reader-vue3

  1. 安装指令
    npm install --save qrcode-reader-vue3
    复制
  2. 组件中使用
    <template>
    <div class="scan">
    <qrcode-stream
    :camera="camera"
    @decode="onDecode"
    @init="onInit"
    style="height: 100vh;"
    >
    <div>
    <div class="qr-scanner">
    <div class="box">
    <div class="line"></div>
    <div class="angle"></div>
    </div>
    </div>
    </div>
    </qrcode-stream>
    </div>
    </template>
    <script lang="ts" scope>
    import { QrcodeStream } from "qrcode-reader-vue3";
    import { defineComponent, ref, onMounted } from "vue";
    export default defineComponent({
    components: { QrcodeStream },
    setup(props) {
    let camera = ref<any>();
    let error = ref<string>('');
    //回调扫描结果
    function onDecode(result) {
    // 扫码结果
    console.log(result)
    if (result !== "") {
    }
    }
    // 检查是否调用摄像头
    async function onInit(promise) {
    try {
    const { capabilities } = await promise;
    console.log(capabilities);
    } catch (error) {
    if (error.name === "NotAllowedError") {
    error = "ERROR: 您需要授予相机访问权限";
    } else if (error.name === "NotFoundError") {
    error = "ERROR: 这个设备上没有摄像头";
    } else if (error.name === "NotSupportedError") {
    error = "ERROR: 所需的安全上下文(HTTPS、本地主机)";
    } else if (error.name === "NotReadableError") {
    error = "ERROR: 相机被占用";
    } else if (error.name === "OverconstrainedError") {
    error = "ERROR: 安装摄像头不合适";
    } else if (error.name === "StreamApiNotSupportedError") {
    error = "ERROR: 此浏览器不支持流API";
    } else if (error.name === "InsecureContextError") {
    error =
    "ERROR: 仅允许在安全上下文中访问摄像机。使用HTTPS或本地主机,而不是HTTP。";
    } else {
    error = "ERROR:摄像机错误";
    }
    }
    }
    return {
    camera,
    onDecode,
    onInit,
    };
    },
    });
    </script>
    复制

注:运行在vue3.0环境,
vue-qrcode-reader再vue3.0中不生效

@zxing/library

  1. 安装指令
    npm install @zxing/library
    复制
  2. 项目中使用
    <template>
    <div class="QrCode">
    <video ref="video" height="100%" width="100%" id="video" autoplay></video>
    </div>
    <div class="Qr_scanner">
    <div class="box">
    <div class="line_row">
    <div class="line"></div>
    </div>
    <div class="angle"></div>
    </div>
    </div>
    </template>
    <script lang="ts" scope>
    import { BrowserMultiFormatReader } from "@zxing/library";
    import {
    defineComponent,
    reactive,
    onBeforeUnmount,
    onMounted,
    } from "vue";
    export default defineComponent({
    setup(props) {
    let codeReader = reactive(new BrowserMultiFormatReader());
    onMounted(() => {
    openScan();
    });
    function openScan() {
    codeReader
    .getVideoInputDevices()
    .then((videoInputDevices) => {
    console.log("videoInputDevices", videoInputDevices, "摄像头设备");
    // 默认获取第一个摄像头设备id
    let firstDeviceId = videoInputDevices[0].deviceId; // 根据id选择摄像头
    if (videoInputDevices.length > 1) {
    // 华为手机有6个摄像头,前三个是前置,后三个是后置,第6个摄像头最清晰
    if (videoInputDevices.length > 5) {
    firstDeviceId = videoInputDevices[5].deviceId;
    } else {
    // 判断是否后置摄像头
    if (videoInputDeviceslablestr.indexOf("back") > -1) {
    firstDeviceId = videoInputDevices[0].deviceId;
    } else {
    firstDeviceId = videoInputDevices[1].deviceId;
    }
    }
    }
    decodeFromInputVideoFunc(firstDeviceId);
    })
    .catch((err) => {
    alert(err)
    });
    };
    let decodeFromInputVideoFunc = (firstDeviceId: any) => {
    codeReader.decodeFromInputVideoDeviceContinuously(
    firstDeviceId, // firstDeviceId 为null 时默认选择面向环境的摄像头
    "video",
    (result: any, err) => {
    if (result) {
    alert(result);
    console.log(result, "扫描结果");
    }
    if (err && !err) {
    console.error(err);
    }
    }
    );
    };
    onBeforeUnmount(() => {
    codeReader.reset();
    });
    return {
    codeReader,
    };
    },
    });
    </script>
    <style scoped>
    .QrCode {
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.2);
    /* background: red; */
    position: relative;
    }
    #video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    }
    /* // 二维码动画 */
    .Qr_scanner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9;
    width: 100%;
    height: 100%;
    position: relative;
    background-color: rgba(0, 0, 0, 0.5);
    }
    .Qr_scanner .box {
    width: 75vw;
    height: 75vw;
    max-height: 75vh;
    max-width: 75vh;
    position: relative;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
    border: 1px solid rgb(43, 113, 254);
    }
    .line_row {
    width: 100%;
    overflow: hidden;
    background-image: linear-gradient(
    0deg,
    transparent 24%,
    rgba(136, 176, 255, 0.1) 25%,
    rgba(136, 176, 255, 0.1) 26%,
    transparent 27%,
    transparent 74%,
    rgba(136, 176, 255, 0.1) 75%,
    rgba(136, 176, 255, 0.1) 76%,
    transparent 77%,
    transparent
    ),
    linear-gradient(
    90deg,
    transparent 24%,
    rgba(136, 176, 255, 0.1) 25%,
    rgba(136, 176, 255, 0.1) 26%,
    transparent 27%,
    transparent 74%,
    rgba(136, 176, 255, 0.1) 75%,
    rgba(136, 176, 255, 0.1) 76%,
    transparent 77%,
    transparent
    );
    background-size: 3rem 3rem;
    background-position: -1rem -1rem;
    animation: Heightchange 2s infinite;
    animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
    animation-delay: 1.4s;
    border-bottom: 1px solid rgba(136, 176, 255, 0.1);
    display: flex;
    justify-content: center;
    align-items: flex-end;
    }
    .Qr_scanner .line {
    width: 100%;
    height: 3px;
    background: #2b71fe;
    filter: blur(4px);
    }
    .Qr_scanner .box:after,
    .Qr_scanner .box:before,
    .Qr_scanner .angle:after,
    .Qr_scanner .angle:before {
    content: "";
    display: block;
    position: absolute;
    width: 78px;
    height: 78px;
    border: 0.3rem solid transparent;
    }
    .Qr_scanner .box:after,
    .Qr_scanner .box:before {
    top: -7px;
    border-top-color: #2b71fe;
    }
    .Qr_scanner .angle:after,
    .Qr_scanner .angle:before {
    bottom: -7px;
    border-bottom-color: #2b71fe;
    }
    .Qr_scanner .box:before,
    .Qr_scanner .angle:before {
    left: -7px;
    border-left-color: #2b71fe;
    }
    .Qr_scanner .box:after,
    .Qr_scanner .angle:after {
    right: -7px;
    border-right-color: #2b71fe;
    }
    @keyframes radar-beam {
    0% {
    transform: translateY(-100%);
    }
    100% {
    transform: translateY(0);
    }
    }
    @keyframes Heightchange {
    0% {
    height: 0;
    }
    100% {
    height: 100%;
    }
    }
    </style>
    复制
    注:如果报错:Can’t enumerate devices, method not supported.
    扫码能运行在https,和本地上(用http://localhost:8080/,,不要用IP:192.168.xx.xx:8080)
    可以运行中vue3.0和vue2.0环境中
  3. 相机授权的时候可以点击拒绝,拒绝后就不能够在调取了
    ZXing 库本身并不直接提供重新获取权限的专用 API。通常,JavaScript 库是无法直接在用户拒绝权限后重新触发权限请求的。
    调用原生的相机监听方法:
    调起相机之前先看一下用户有没有授权,如果没有授权就让他重新进入页面进行授权
    navigator.mediaDevices.getUserMedia({ video: true })
    .then(stream => {
    // 用户授权了相机权限,可以进行后续操作
    console.log('相机已授权')
    decodeFromInputVideoFunc(firstDeviceId);
    })
    .catch(err => {
    // 处理错误,可能是因为权限被拒绝
    console.log('获取相机权限失败:', err);
    });
    复制

vue-qrcode-reader

  1. 安装指令
    npm install vue-qrcode-reader
    复制
  2. 组件中的应用
    <template>
    <div class="scan">
    <qrcode-stream
    :camera="camera"
    @decode="onDecode"
    @init="onInit"
    style="height: 100vh;"
    >
    <div>
    <div class="qr-scanner">
    <div class="box">
    <div class="line"></div>
    <div class="angle"></div>
    </div>
    </div>
    </div>
    </qrcode-stream>
    </div>
    </template>
    <script>
    // 引入
    import { QrcodeStream } from "vue-qrcode-reader";
    export default {
    // 注册
    components: { QrcodeStream },
    data() {
    return {
    camera: "auto",
    result: "", // 扫码结果信息
    error: "" // 错误信息
    };
    },
    created() {},
    methods: {
    //回调扫描结果
    onDecode(result) {
    if (result !== "") {
    this.$emit("ok", result);
    }
    },
    // 检查是否调用摄像头
    async onInit(promise) {
    try {
    const { capabilities } = await promise;
    console.log(capabilities);
    } catch (error) {
    if (error.name === "NotAllowedError") {
    this.error = "ERROR: 您需要授予相机访问权限";
    } else if (error.name === "NotFoundError") {
    this.error = "ERROR: 这个设备上没有摄像头";
    } else if (error.name === "NotSupportedError") {
    this.error = "ERROR: 所需的安全上下文(HTTPS、本地主机)";
    } else if (error.name === "NotReadableError") {
    this.error = "ERROR: 相机被占用";
    } else if (error.name === "OverconstrainedError") {
    this.error = "ERROR: 安装摄像头不合适";
    } else if (error.name === "StreamApiNotSupportedError") {
    this.error = "ERROR: 此浏览器不支持流API";
    } else if (error.name === "InsecureContextError") {
    this.error =
    "ERROR: 仅允许在安全上下文中访问摄像机。使用HTTPS或本地主机,而不是HTTP。";
    } else {
    this.error = "ERROR:摄像机错误";
    }
    this.$emit("err", this.error);
    }
    }
    }
    };
    </script>
    <style scoped>
    </style>
    复制
转载请注明出处或者链接地址:https://www.qianduange.cn//article/17040.html
标签
评论
还可以输入200
共0条数据,当前/页
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!