We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hi, thanks for this demo, saved me a lot of time!
I've made some changes based on my app. Hope these tips help!
<video/>
tick()
transform
<template> <div class="scaner" ref="scaner" @click="resume"> <!--<div class="banner" v-if="showBanner">--> <!-- <i class="close_icon" @click="() => showBanner = false"></i>--> <!-- <p class="text">若当前浏览器无法扫码,请切换其他浏览器尝试</p>--> <!--</div>--> <div class="cover"> <p class="line"></p> <!--<span class="square top left"></span>--> <!--<span class="square top right"></span>--> <!--<span class="square bottom right"></span>--> <!--<span class="square bottom left"></span>--> <p class="tips">{{ active ? '扫描二维码':'扫码暂停 点击屏幕继续扫码' }}</p> </div> <div class="video-wrapper" ref="CanvasWrapper"> <video class="source" ref="video" > <!--v-show="showPlay"--> <!--controls--> </video> <canvas class="canvas-video" ref="canvas" /> <div v-if="code != null" class="code-indicator" :style="{ top: codePosition.y+'px', left:codePosition.x+'20px', }"></div> </div> <!--<button v-show="showPlay" @click="run">开始</button>--> </div> </template> <script> // eslint-disable-next-line no-unused-vars import adapter from 'webrtc-adapter'; import jsQR from 'jsqr'; export default { name: 'Scaner', props: { // 使用后置相机 useBackCamera: { type: Boolean, default: true }, // 扫描识别后停止 stopOnScaned: { type: Boolean, default: true }, drawOnfound: { type: Boolean, default: true }, // 线条颜色 lineColor: { type: String, default: '#03C03C' }, // 线条宽度 lineWidth: { type: Number, default: 2 }, responsive: { type: Boolean, default: false } }, data () { return { showPlay: false, showBanner: true, // videoWidth: null, // videoHeight: null, active: false, code:null, } }, computed: { codePosition(){ if (this.code == null){ return null; } return { x: this.code.location.topLeftCorner.x + (this.code.location.bottomRightCorner.x - this.code.location.topLeftCorner.x)/2 - 25, y: this.code.location.topLeftCorner.y + (this.code.location.bottomRightCorner.y - this.code.location.topLeftCorner.y)/2 - 25, } }, }, watch: { // @Depracated! // active: { // immediate: true, // handler(active) { // if (!active) { // this.pause(); // //this.fullStop(); // } // } // } }, methods: { // 画线 drawLine (begin, end) { this.canvas.beginPath(); this.canvas.moveTo(begin.x, begin.y); this.canvas.lineTo(end.x, end.y); this.canvas.lineWidth = this.lineWidth; this.canvas.strokeStyle = this.lineColor; this.canvas.stroke(); }, // 画框 drawBox (location) { if (this.drawOnfound) { this.drawLine(location.topLeftCorner, location.topRightCorner); this.drawLine(location.topRightCorner, location.bottomRightCorner); this.drawLine(location.bottomRightCorner, location.bottomLeftCorner); this.drawLine(location.bottomLeftCorner, location.topLeftCorner); } }, tick () { if (this.$refs.video && this.$refs.video.readyState === this.$refs.video.HAVE_ENOUGH_DATA) { //.这里不设置会影响分辨率 this.$refs.canvas.width = this.$refs.video.clientWidth; this.$refs.canvas.height = this.$refs.video.clientHeight; this.canvas.drawImage(this.$refs.video, 0, 0, this.$refs.canvas.width, this.$refs.canvas.height); const imageData = this.canvas.getImageData(0, 0, this.$refs.canvas.width, this.$refs.canvas.height); let code = false; try { code = jsQR(imageData.data, imageData.width, imageData.height); } catch (e) { console.error(e); } if (code) { //@Deprecated! //this.drawBox(code.location); this.found(code); } } this.run(); }, // 初始化 setup () { if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { this.previousCode = null; this.parity = 0; this.active = true; this.canvas = this.$refs.canvas.getContext("2d"); const facingMode = this.useBackCamera ? { exact: 'environment' } : 'user'; const handleSuccess = stream => { if (this.$refs.video.srcObject !== undefined) { this.$refs.video.srcObject = stream; } else if (window.videoEl.mozSrcObject !== undefined) { this.$refs.video.mozSrcObject = stream; } else if (window.URL.createObjectURL) { this.$refs.video.src = window.URL.createObjectURL(stream); } else if (window.webkitURL) { this.$refs.video.src = window.webkitURL.createObjectURL(stream); } else { this.$refs.video.src = stream; } this.$refs.video.playsInline = true; const playPromise = this.$refs.video.play(); playPromise.catch(() => (this.showPlay = true)); playPromise.then(this.run); }; navigator.mediaDevices .getUserMedia({ video: { facingMode, width: 1280, height: 720 } }) .then(handleSuccess) .catch(() => { navigator.mediaDevices .getUserMedia({ video: true }) .then(handleSuccess) .catch(error => { this.$emit("error-captured", error); }); }); } }, resume(){ if (!this.active){ this.code = null; this.active = true; this.$refs.video.play(); this.run(); } }, pause(){ this.active = false; this.$refs.video.pause(); }, run () { if (this.active) { setTimeout(()=>{ this.tick(); },50); //@Deprecated! //requestAnimationFrame(this.tick); } }, found (code) { this.code = code; let codeString = code.data; this.$emit("code-scanned", codeString); if (this.stopOnScaned){ this.pause(); } // @Depracated! // if (this.previousCode !== codeString) { // this.previousCode = codeString; // } else if (this.previousCode === codeString) { // this.parity += 1; // } // if (this.parity > 2) { // this.code = code; // this.parity = 0; // this.$emit("code-scanned", codeString); // if (this.stopOnScaned){ // this.pause(); // } // } }, // 完全停止 fullStop () { if (this.$refs.video && this.$refs.video.srcObject) { this.$refs.video.srcObject.getTracks().forEach(t => t.stop()); } } }, mounted () { this.setup(); }, beforeDestroy () { this.fullStop(); } } </script> <style lang="css" scoped> .scaner { background: #000000; position: absolute; top: 0px; left: 0; width: 100%; height: 100%; } .scaner .video-wrapper{ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /*width: 100%;*/ /*min-width: 100vh;*/ /*height: 100%;*/ /*min-height: 100vw;*/ } .scaner .video-wrapper video.source{ position: relative; min-width: 100vw; min-height: 100vh; } .scaner .video-wrapper .canvas-video{ position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 0; } .scaner .video-wrapper .code-indicator{ position: absolute; width: 50px; height: 50px; border-radius: 100px; background-color: #5F68E8; border: 3px solid #fff; z-index: 9999; } .scaner .cover { width: 100%; height: 60vh; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-60%); z-index: 1111; } .scaner .cover .tips { position: absolute; bottom: -20%; width: 100%; text-align: center; font-size: 14px; color: #FFFFFF; opacity: 0.8; } .scaner .cover .line { width: 80%; height: 6px; border-radius: 100%; margin-left: 10%; background: #5F68E8; background: linear-gradient(to right, #0000, #5F68E8, #0165FF, #5F68E8, #0000); position: absolute; animation: scan 3s infinite ease, opacity 3s infinite ease; animation-fill-mode: both; } @keyframes scan { 0% {transform: translate3d(0,0,0)} 100% {transform: translate3d(0,60vh,0)} } @keyframes opacity { 0% {opacity:0} 15% {opacity:1} 45% {opacity:1} 100% {opacity:0} } </style>
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Hi, thanks for this demo, saved me a lot of time!
I've made some changes based on my app. Hope these tips help!
<video/>
tick()
running. I made a new animation based ontransform
.The text was updated successfully, but these errors were encountered: