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

news2025/2/26 22:29:27

一、效果

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

二、实现过程 

 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)),
    },
  },
});

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

二维码

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1528645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图论03-所有可能路径(Java)

3.所有可能路径 题目描述 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节点的列表&#xff08;即从节点 i 到…

TypeScript(六)条件类型,函数,装饰器

条件类型 TypeScript 中的条件类型是一种高级类型&#xff0c;它使我们根据不同的条件创建更复杂的类型。 TS中的条件类型就是在类型中添加条件分支&#xff0c;以支持更加灵活的泛型 条件类型允许我们根据某个类型的属性是否满足某个条件&#xff0c;来确定最终的类型。 type…

【海贼王的数据航海】排序——冒泡|快速|归并排序|总结

目录 1 -> 交换排序 1.1 -> 冒泡排序 1.1.1 -> 代码实现 1.2 -> 快速排序 1.2.1 -> hoare版本 1.2.2 -> 挖坑法 1.2.3 -> 前后指针法 1.2.4 -> 快速排序(递归版) 1.2.5 -> 快速排序(非递归版) 2 -> 归并排序 2.1 -> 归并排序 2.…

泛微 OA - 根据流程 requestid 获取流程中的附件

泛微 OA - 根据流程 requestid 获取流程中的附件 在泛微 OA 流程中&#xff0c;附件是通过加密上传的&#xff0c;如果在第三方系统想要调用 OA 系统获取 OA 附件&#xff0c;暂时没有很好的方法实现。但是可以在本地进行调用&#xff0c;得到附件 url 地址、附件 id、附件上传…

蓝桥杯练习02随机数生成器

随机数生成器 介绍 实际工作中随机数的使用特别多&#xff0c;比如随机抽奖、随机翻牌。通过随机数还能实现很多有趣的效果&#xff0c;比如随机改变元素的位置或颜色。 本题需要在已提供的基础项目中使用JS知识封装一个函数&#xff0c;该函数可以根据需要&#xff0c;生成指…

01. 【Android教程】系统背景及结构概述

1. Android 的历史 Android 一词的本意指“人形机器人”&#xff0c;安迪•鲁宾 (Andy Rubin) 在 2003 年以此名创办了 Android 公司并开始召集团队研发 Android 系统。后于 2005 年被 Google 收购&#xff0c;安迪•鲁宾随后任 Google 工程部副总裁&#xff0c;继续负责 Andr…

数据可信流通:从运维信任到技术信任

1.数据可信流通概念 "数据可信流通"通常指的是确保数据在不同系统、应用程序或者组织之间的传输和交换过程中的可信性、完整性和安全性。在数据流通的过程中&#xff0c;确保数据的真实性、完整性和保密性是非常重要的&#xff0c;尤其是涉及到敏感信息或者重要数据…

大数据开发--01.初步认识了解

一.环境准备 1.使用虚拟机构建至少三台linux服务器 2.使用公有云来部署服务器 二.大数据相关概念 大数据是指处理和分析大规模数据集的一系列技术、工具和方法。这些数据集通常涉及海量的数据&#xff0c;包括结构化数据&#xff08;如关系型数据库中的表格&#xff09;以及…

Verdaccio部署及基础使用

1. Verdaccio 简介 Verdaccio&#xff0c;是一个轻量级的 npm 私有仓库的开源解决方案。npm是一个基于http的协议&#xff0c;用来存放软件包并且维护版本和依赖&#xff0c;利用 http 提供的 url路径 来对软件包进行增删改查。所以 Verdaccio 这款软件的核心就是实现 npm协议…

机器人路径规划:基于双向A*算法(bidirectional a star)的机器人路径规划(提供Python代码)

一、双向A*算法简介 传统A*算法是一种静态路网中求解最短路径最有效的方法&#xff0c; 它结合了BFS 算法和迪杰斯特拉算法(Dijkstra)的优点。 和迪杰斯特拉算法(Dijkstra)一样&#xff0c; A*算法能够用于 搜索最短路径&#xff1b; 和BFS 算法一样&#xff0c; A*算法可以用…

从头手搓一台ros2复合机器人(带机械臂)

一.前言 大家好呀&#xff0c;从本小节开始我们就步入了仿真篇&#xff0c;主要对机器人仿真进行介绍与操作&#xff0c;当然仿真有优点也有缺陷&#xff0c;基于对此学习&#xff0c;我们可以对上几小节创建的小车模型模拟硬件的特性&#xff0c; 比如&#xff1a; 有多重…

打开磁盘清理工具的9种方法,总有一种适合你

前言 你可以在Windows 10和11上使用许多第三方磁盘清理工具来进行清理。但是,别忘了Windows包含自己的磁盘清理工具,你可以使用该工具释放硬盘存储空间。一些第三方替代方案可能有更广泛的清理选项和功能,但磁盘清理仍然是消除多余文件的完美工具。 每个用户都应该不时地进…

vue 部署 abap BSP

How to Create a Vue.Js App with VS Code and Deploy... - SAP Community 详情见上面这个教程连接 Open VS Code and open a terminal window and run npm install -g vue/cli restart vscode. Open a terminal window again and go to your workspace folder to create the…

使用echart绘制拓扑图,树类型,自定义tooltip和label样式,可收缩

效果如图&#xff1a; 鼠标移上显示 vue3 - ts文件 “echarts”: “^5.4.3”, import { EChartsOption } from echarts import * as echarts from echarts/core import { TooltipComponent } from echarts/components import { TreeChart } from echarts/charts import { C…

VR历史建筑漫游介绍|虚拟现实体验店|VR设备购买

VR历史建筑漫游是一种利用虚拟现实技术&#xff0c;让用户可以身临其境地参观和探索历史建筑的体验。通过VR头显和相关设备&#xff0c;用户可以在虚拟环境中自由移动和互动&#xff0c;感受历史建筑的真实氛围和文化内涵。 在VR历史建筑漫游中&#xff0c;您可以选择不同的历史…

拿捏指针(三)

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 前言 在这之前我们学习了《拿捏指针&#xff08;一&#xff09;》&#xff0c;《拿…

Centos7部署使用TELEMAC-MASCARET

Background TELEMAC-MASCARET是一款研究水动力学和水文学领域的高性能数值仿真开源软件。MASCARET&#xff08;1980&#xff09;和 TELEMAC&#xff08;1987&#xff09;最初是由法电集团所属的法国国立水利与环境实验室开发&#xff0c;随后整合为TELEMAC-MASCARET并由法英德三…

后端系统开发之——创建注册接口

原文地址&#xff1a;后端系统开发之——创建注册接口 - Pleasure的博客 下面是正文内容&#xff1a; 前言 这是一篇SpringBoot项目的实践篇。 主要用于介绍如何从零开始搭建某一种类型的系统。 个人认为&#xff0c;只要后端逻辑完善了&#xff0c;纵使前端页面千变万化都可…

【DL经典回顾】激活函数大汇总(二十四)(Absolute附代码和详细公式)

激活函数大汇总&#xff08;二十四&#xff09;&#xff08;Absolute附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可或缺的…

个人开发者上架App流程

摘要 个人开发者完全可以将自己开发的App上传至应用商店进行上架。本文将介绍上架流程的通用步骤&#xff0c;包括确定App功能和定位、准备相关资料、开发App、提交审核、发布App和宣传推广等内容。 引言 个人开发者在如今的移动应用市场中也有机会将自己的作品推向更广泛的…