// yarn add @zxing/library 安装zxing插件
<template>
<div class="page-scan">
<!--返回-->
<!-- <van-nav-bar
title="扫描二维码/条形码"
fixed
@click-left="clickIndexLeft()"
class="scan-index-bar">
<template #left>
<van-icon name="arrow-left" size="18" color="#fff"/>
<span style="color: #fff">取消</span>
</template>
</van-nav-bar> -->
<!-- 扫码区域 -->
<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> -->
<!-- 扫码样式二 -->
<div class="qr-scanner">
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
<div class="back-arrow" @click="clickIndexLeft">
<van-icon name="arrow-left" color="#fff" />
</div>
</div>
</div>
</template>
<script>
// WebRTC适配器 只需要引入就ok
import 'webrtc-adapter';
import { BrowserMultiFormatReader } from '@zxing/library'
export default {
name: 'scanCodePage',
data() {
return {
codeReader: null,
}
},
mounted() {
this.codeReader = new BrowserMultiFormatReader()
this.openScan()
},
beforeUnmount() {
this.codeReader && this.codeReader.reset()
},
methods: {
async openScan() {
// this.codeReader.listVideoInputDevices().then(videoInputDevices => {
// // 默认获取第一个摄像头设备id
// videoInputDevices.forEach((device) =>
// alert(`${device.label}, ${device.deviceId}`)
// )
// let firstDeviceId = videoInputDevices[0].deviceId
// this.codeReader && this.codeReader.reset() // 重置
// this.decodeFromInputVideoFunc(firstDeviceId)
// })
// this.codeReader.getVideoInputDevices().then((videoInputDevices) => {
this.codeReader.listVideoInputDevices().then((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.codeReader && this.codeReader.reset() // 重置
this.decodeFromInputVideoFunc(firstDeviceId)
}).catch(err => {
console.error(err)
})
},
decodeFromInputVideoFunc(firstDeviceId) {
this.codeReader.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {
if (result) {
console.log('扫描结果', result)
if (result.text) {
this.clickIndexLeft(result.text)
}
}
if (err && !(err)) {
console.error(err)
}
})
},
// 返回上一页
clickIndexLeft(result) {
this.codeReader && this.codeReader.reset()
this.codeReader = null
this.$route.params.result = result
this.$router.back()
}
}
}
</script>
<style lang="scss" scope>
// #region
// .scan-index-bar{
// background-image: linear-gradient( -45deg, #42a5ff ,#59cfff);
// }
// .van-nav-bar__title{
// color: #fff !important;
// }
// #endregion
/**
扫码样式一
*/
.QrCode {
width: 100vw;
height: 100vh;
position: relative;
#video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
// #region
// .Qr_scanner {
// position: fixed;
// top: 0;
// left: 0;
// right: 0;
// bottom: 0;
// z-index: 9;
// width: 100%;
// height: 100%;
// 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%);
// 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;
// // opacity: 0.58;
// 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%;
// }
// }
// #endregion
/**
扫码样式二
*/
.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: relative;
// background-color: #111;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9;
width: 100%;
height: 100%;
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: 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);
}
}
.qr-scanner .back-arrow {
position: fixed;
top: 20px;
left: 20px;
width: 30px;
height: 30px;
border-radius: 100%;
background-color: rgba(0, 0, 0, 0.3);
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
}
</style>