安装:
npm install @zxing/library
创建组件:
<template>
<div class="qrcode">
<video
ref="video"
id="video"
class="scan-video"
v-show="scanTextData.showScanBoxInfo"
autoplay
></video>
<div class="scan-img" v-show="scanTextData.showScanBoxInfo">
<div class="scan-frame">
<span class="left-t"></span>
<span class="right-t"></span>
<span class="left-b"></span>
<span class="right-b"></span>
<span class="cross-line"></span>
</div>
</div><div class="scan-tip" v-show="scanTextData.showScanBoxInfo">
{{ scanTextData.tipMsg }}
</div>
</div>
</template>
<script>
import { BrowserMultiFormatReader } from "@zxing/library";
export default {
name: "scanCodePage",
data() {
return {
scanTextData: {
loadingShow: false,
codeReader: null,
scanText: "",
vin: null,
tipMsg: "将二维码置于屏幕中,即可识别",
tipShow: false,
showScanBox: false,
showScanBoxInfo: false,
},
hasBind: false,
dataObj: { qrCodeId: undefined },
};
},
components: {},
created() {
this.toScanCode();
},
destroyed() {
this.scanTextData.codeReader.reset();
},
methods: {
toScanCode() {
console.log("识别二维码", this.dataObj);
this.scanTextData.codeReader = new BrowserMultiFormatReader();
this.scanTextData.showScanBox = true;
this.openScan();
},
cancelScan() {
//识别完停止使用摄像头
let Video = document.getElementById("video");
Video.srcObject.getTracks()[0].stop();
this.scanTextData.codeReader.reset(); // 重置
this.scanTextData.showScanBox = false;
setTimeout(() => {
this.scanTextData.showScanBoxInfo = false;
}, 1000);
},
async openScan() {
this.scanTextData.codeReader
.getVideoInputDevices()
.then((videoInputDevices) => {
this.scanTextData.tipShow = true;
this.scanTextData.tipMsg = "正在调用摄像头...";
console.log("videoInputDevices", videoInputDevices);
// 默认获取第一个摄像头设备id
let firstDeviceId = videoInputDevices[0].deviceId;
// 获取第一个摄像头设备的名称
const videoInputDeviceslablestr = JSON.stringify(
videoInputDevices[0].label
);
if (videoInputDevices.length > 1) {
// 判断是否后置摄像头
if (videoInputDeviceslablestr.indexOf("back") > -1) {
firstDeviceId = videoInputDevices[0].deviceId;
} else {
firstDeviceId = videoInputDevices[1].deviceId;
}
}
this.decodeFromInputVideoFunc(firstDeviceId);
})
.catch((err) => {
this.scanTextData.tipShow = false;
console.error(err);
});
},
decodeFromInputVideoFunc(firstDeviceId) {
this.scanTextData.codeReader.reset(); // 重置
this.scanTextData.scanText = "";
this.scanTextData.codeReader.decodeFromInputVideoDeviceContinuously(
firstDeviceId,
"video",
(result, err) => {
this.scanTextData.tipMsg = "将二维码置于屏幕中,即可识别";
this.scanTextData.scanText = "";
setTimeout(() => {
this.scanTextData.showScanBoxInfo = true;
}, 1000);
if (result) {
if (result.text) {
let decodedText = result.text;
// 返回出去的结果
this.$emit('qrcodes',decodedText)
}
} else {
// console.log('没出来?',result,err)
}
if (err && !err) {
this.scanTextData.tipMsg = "识别失败";
setTimeout(() => {
this.scanTextData.tipShow = false;
}, 2000);
console.error(err);
}
}
);
},
},
};
</script>
<style scoped lang="scss">
body {
margin: 0;
background-color: rgb(133, 133, 133);
}
.qrcode {
position: relative;
height: 100%;
width: 100%;
overflow: hidden;
}
.scan-index-bar {
background-image: linear-gradient(-45deg, #42a5ff, #59cfff);
}
.van-nav-bar__title {
color: #fff !important;
}
.scan-box {
position: fixed;
top: 0;
left: 0;
z-index: 5;
height: 100%;
width: 100vw;
.scan-cacel {
position: absolute;
top: 30px;
left: 30px;
z-index: 9;
color: #fff;
font-size: 35px;
}
}
.scan-video {
height: 100vh;
width: 100vw;
object-fit: cover;
}
.scan-img {
width: 300px;
height: 300px;
position: fixed;
top: 55%;
left: 77%;
margin-top: -200px;
margin-left: -250px;
z-index: 6;
.scan-frame {
width: 100%;
height: 100%;
position: relative;
.left-t,
.right-t,
.left-b,
.right-b {
position: absolute;
width: 80px;
height: 80px;
}
.left-t {
top: 0;
left: 0;
border-top: 2px solid #17b1b7;
border-left: 2px solid #17b1b7;
}
.right-t {
top: 0;
right: 0;
border-top: 2px solid #17b1b7;
border-right: 2px solid #17b1b7;
}
.left-b {
bottom: 0;
left: 0;
border-bottom: 2px solid #17b1b7;
border-left: 2px solid #17b1b7;
}
.right-b {
bottom: 0;
right: 0;
border-bottom: 2px solid #17b1b7;
border-right: 2px solid #17b1b7;
}
.cross-line {
width: 300px;
height: 5px;
background: linear-gradient(
to right,
rgba(255, 255, 255, 0),
#5dddd3,
rgba(255, 255, 255, 0)
);
position: absolute;
top: 0;
left: 0;
animation: identifier_p 5s infinite;
}
@keyframes identifier_p {
0% {
top: 0%;
}
50% {
top: 100%;
}
100% {
top: 0;
}
}
}
}
.scan-tip {
width: 100vw;
text-align: center;
margin-bottom: 10vh;
color: white;
font-size: 5vw;
position: absolute;
bottom: 50px;
left: 0;
color: #fff;
}
.page-scan {
overflow-y: hidden;
}
</style>
如果报错:Can’t enumerate devices, method not supported.
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
切记一件件事:扫码能运行在https,和本地上(用http://localhost:1314/,,不要用IP:192.168.xx.xx:1314)
http是不行的
如果写成页面的形式可以通过非父子传值(eventBus)
写一个js
import Vue from 'vue'
var eventBus = new Vue({});
export default eventBus;
父子组件都引入:::::::
子组件
返回上一层:
this.$router.go(-1)
event.$emit("自定义事件",data)
父组件
//父组件监听
eventBus.$on("子组件里面的自定义事件",(data)=>{
// data= 子组件发过来的数据
console.log(data)
})
祝愿永远不会报错,copy成功
补充:相机授权的时候可以点击拒绝,拒绝后就不能够在调取了
ZXing 库本身并不直接提供重新获取权限的专用 API。通常,JavaScript 库是无法直接在用户拒绝权限后重新触发权限请求的。
在网页开发中,一旦用户拒绝了权限请求,通常最佳的做法是引导用户手动开启权限。用户可以通过浏览器设置或者在地址栏的网站信息中找到相关权限设置,然后重新授权。
调用原生的相机监听方法:
调起相机之前先看一下用户有没有授权,如果没有授权就让他重新进入页面进行授权
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
// 用户授权了相机权限,可以进行后续操作
console.log('相机已授权')
})
.catch(err => {
// 处理错误,可能是因为权限被拒绝
console.log('获取相机权限失败:', err);
});```