前言:一定是https协议,一定是https协议,一定是https协议,识别的是二维码。条形码估计不太行(因为太小了)
1:安装 "@zxing/library": "^0.20.0",
npm install @zxing/library --save (最好别用cnpm)
或
yarn add @zxing/library
2:上代码 (我这是放在弹窗里面了) openScan:初始化的方法
先看看你们的协议是http的还是https的
一定是https协议
一定是https协议
一定是https协议
不然摄像头会报错,原因是因为会被浏览器认为是不安全的操作
<button @click="scan"></button>
<scanIndex ref="scanIndex"></scanIndex>
methods:{
scan(){
this.$refs.scanIndex.title= "测试";
this.$refs.scanIndex.dialogAddVisible = true;
this.$refs.scanIndex.openScan();
},
}
<template>
<el-dialog :class="{dialogClass:dialogWidth=='100%'}" title="提示" :visible.sync="dialogAddVisible" :width="dialogWidth" @close="resetScan">
<span slot="title">{{ title }}</span>
<div class="dashboard-container" style="position: relative">
<!-- <div class="dashboard-text">name: {{ name }}</div> -->
<!-- 提示语 -->
<!-- <div v-show="tipShow" class="scan-tip">{{ tipMsg }}</div> -->
<!-- 扫码区域 -->
<video
style="object-fit:fill;"
ref="video"
id="video"
class="scan-video"
:width="videoWidth"
:height="videoHeight"
autoplay
></video>
<div class="qr-scanner">
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
</div>
<!-- <div >{{scanText}}</div> -->
</div>
</el-dialog>
</template>
<script>
import { BrowserMultiFormatReader } from "@zxing/library";
export default {
name: "Dashboard",
computed: {},
props: ["title"],
data() {
return {
dialogAddVisible: false,
codeReader: null,
scanText: "", // 扫码结果文本内容
dialogWidth:"60%",
videoWidth:"100%",
videoHeight:"100%",
};
},
created() {
// 移动端
console.log(this.IsPhone())
if(this.IsPhone()!=null){
this.dialogWidth="100%"
// this.videoWidth="300"
this.videoHeight="450"
}else{
this.dialogWidth="60%"
}
},
destroyed() {
this.resetScan();
},
methods: {
IsPhone() {
let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
//如果包含“Mobile”(是手机设备)则返回true
return flag;
},
resetScan() {
// this.codeReader.hasNavigator=false;
// console.log(this.codeReader)
if (this.codeReader) {
this.codeReader?.reset();
this.codeReader = null;
}
},
async openScan() {
let that = this; // 初始化摄像头
this.codeReader = new BrowserMultiFormatReader();
this.codeReader
.getVideoInputDevices()
.then((videoDevices) => {
that.$message({ type: "success", message: "正在调用摄像头..." });
// that.tipShow = true;
// console.log("get-videoDevices", videoDevices);
// 默认获取摄像头列表里的最后一个设备id,通过几部测试机发现一般前置摄像头位于列表里的前面几位,所以一般获取最后一个的是后置摄像头
let firstDeviceId = videoDevices[videoDevices.length - 1].deviceId;
// 一般获取了手机的摄像头列表里不止一个,有的手机摄像头高级多层,会有变焦摄像头等情况,需要做处理
if (videoDevices.length > 1) {
// 一般通过判断摄像头列表项里的 label 字段,'camera2 0, facing back' 字符串含有 'back' 和 '0',大部分机型是这样,如果有些机型没有,那就还是默认获取最后一个
firstDeviceId = videoDevices.find((el) => {
return (
el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1
);
})
? videoDevices.find((el) => {
return (
el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1
);
}).deviceId
: videoDevices[videoDevices.length - 1].deviceId;
}
// console.log("get-firstDeviceId", firstDeviceId);
this.decodeFromInputVideoFunc(firstDeviceId);
})
.catch((err) => {
// this.tipShow = false;
// console.error(err);
that.$message.error(err);
});
},
decodeFromInputVideoFunc(firstDeviceId) {
let that = this; // 使用摄像头扫描
// this.codeReader.reset(); // 重置
setTimeout(() => {
that.$message({ type: "primary", message: "正在尝试识别..." });
}, 1000);
this.codeReader.decodeFromInputVideoDeviceContinuously(
firstDeviceId,
"video",
(result, err) => {
// that.$message({type:"primary",message:"正在尝试识别..."});
// that.tipMsg = "";
if (result) {
that.scanText = result.text;
if (that.scanText) {
// this.tipShow = false;
// that.$alert(that.scanText, '扫码结果', {
// confirmButtonText: '确定',
// callback: action => {
// // that.$destroy();
// }
// });
that.resetScan();
that.$emit("updateForm", that.scanText);
that.dialogAddVisible = !that.dialogAddVisible;
}
}
}
);
},
// clickIndexLeft(){ // 返回上一页
// this.$destroy();
// this.$router.go(-1);
// // window.location.href = document.referrer;
// }
},
};
</script>
<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
#video {
// width: 100%;
}
.dialogClass /deep/ .el-dialog__body{
padding:0;
}
.dialogClass /deep/ .dashboard-container{
margin: 0px;
}
.qr-scanner {
background-image: linear-gradient(
0deg,
transparent 24%,
rgba(32, 255, 77, 0.1) 25%,
rgba(32, 255, 77, 0.1) 26%,
transparent 27%,
transparent 74%,
rgba(32, 255, 77, 0.1) 75%,
rgba(32, 255, 77, 0.1) 76%,
transparent 77%,
transparent
),
linear-gradient(
90deg,
transparent 24%,
rgba(32, 255, 77, 0.1) 25%,
rgba(32, 255, 77, 0.1) 26%,
transparent 27%,
transparent 74%,
rgba(32, 255, 77, 0.1) 75%,
rgba(32, 255, 77, 0.1) 76%,
transparent 77%,
transparent
);
background-size: 3rem 3rem;
background-position: -1rem -1rem;
width: 100%;
height: 100%;
position: absolute;
top: 0;
// background-color: #111;
}
.qr-scanner .box {
width: 75%;
height: 75%;
max-height: 75%;
max-width: 75%;
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
border: 0.1rem solid rgba(0, 255, 51, 0.2);
}
.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;
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>
3:效果图
PC端
为啥是黑的,因为
手机端
4:结果 result.text是识别成功后的结果 可自行更改