参考:
图像解二维码:qrcode-decoder
摄像头需要在本地和ssl环境下运行
因为qrcode-decoder 组件中引用一直在报错,所以只能放到全局index.html,外部引用了
index.html
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title> <%= htmlWebpackPlugin.options.title %> </title> <script src="https://unpkg.com/qrcode-decoder@0.3.1/dist/index.min.js"></script> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> <script> var qr = new QrcodeDecoder();</script> </body> </html>
HelloWorld.vue
<template> <div class="hello"> <div class="video-container"> <video ref="cameraVideo"></video> <canvas ref="cameraCanvas" width="500" height="500"></canvas> </div> <div class="btns"> <button class="btn" @click="openCamera()">开启摄像</button> <button class="btn" @click="stopCamera()">停止摄像</button> <button class="btn" @click="takePicture()">拍照</button> <button class="btn" @click="downPhoto()">下载</button> </div> <div>二维码地址:{{ qrurl }}</div> </div> </template> <script> console.log(qr) // import QrcodeDecoder from 'qrcode-decoder'; // console.log(QrcodeDecoder) // var qr = new QrcodeDecoder(); export default { name: "HelloWorld", props: { msg: String, }, data() { return { video: undefined, canvas: undefined, qr: undefined, qrurl: "", config: { // video属性设置 video: { width: 500, height: 500, }, }, }; }, methods: { /** * 开启摄像 */ openCamera() { let self = this; navigator.mediaDevices .getUserMedia(self.config) .then((mediaStream) => { //接收一个mediaStream参数与video标签进行对接 self.video.srcObject = mediaStream; self.video.play(); }) .catch((err) => { console.log(err); }); }, // 停止摄像 stopCamera() { self.video.pause(); }, /** * 拍照、canvas绘制 */ takePicture() { let ctx = this.canvas.getContext("2d"); ctx.drawImage(this.video, 0, 0, this.config.video.width, this.config.video.height); let imageData = ctx.getImageData( 0, 0, this.config.video.width, this.config.video.height ); console.log(99, imageData); }, /** * canvas下载图片 */ downPhoto() { const MIME_TYPE = "image/png"; const dlLink = document.createElement("a"); dlLink.download = "测试照片"; dlLink.href = this.canvas.toDataURL(MIME_TYPE); dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(":"); document.body.appendChild(dlLink); dlLink.click(); document.body.removeChild(dlLink); }, }, mounted() { this.video = this.$refs.cameraVideo; this.canvas = this.$refs.cameraCanvas; qr.decodeFromVideo(this.video).then((res) => { this.qrurl = res.data; console.log(res, res.data); }); }, }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> * { padding: 0; margin: 0; } .btn { width: 100px; padding: 10px 0; border-radius: 4px; background: #ff5415; text-align: center; color: #fff; cursor: pointer; border: none; font-size: 16px; } video, canvas { width: 500px; height: 500px; border: 1px solid #ff5415; border-radius: 4px; margin-left: 5px; } .camera-warpper { padding: 20px 0; width: 100%; } .video-container { display: flex; align-items: center; justify-content: center; } .btns { padding: 20px 0; display: flex; align-items: center; justify-content: center; } button + button { margin-left: 10px; } </style>