提交 bdf8a42c 编写于 作者: MuGuiLin's avatar MuGuiLin 🏡

update

上级 7fb834e8
......@@ -3,28 +3,36 @@
padding: 0;
}
.h2 {
.h1 {
padding: 10px;
text-align: center;
}
.reader {
.menu{
text-align: center;
font-size: 16px;
}
.canvas {
display : none;
box-sizing: border-box;
position : fixed;
top : 0;
right : 0;
bottom : 0;
left : 0;
width : 100vw;
height : 100vh;
.menu nav{
display: inline-block;
padding: 20px;
font-size: 20px;
font-weight: bold;
cursor: pointer;
}
.menu nav.active{
color: #42b983;
}
.main{
}
.reader .sweep {
.main .reader {
text-align: center;
font-size: 16px;
}
.main .reader .sweep {
position : relative;
margin : 20px;
padding : 12px;
......@@ -37,18 +45,18 @@
overflow : hidden;
}
.reader .sweep input {
.main .reader .sweep input {
position : absolute;
font-size: 100px;
opacity : 0;
}
.reader .imgurl {
.main .reader .imgurl {
margin : 20px;
text-align: center;
}
.reader .imgurl img {
.main .reader .imgurl img {
margin : 20px;
padding : 10px;
border : 1px solid gray;
......@@ -57,10 +65,22 @@
height : 260px;
}
.reader .result {
.main .reader .result {
box-sizing : border-box;
padding : 10px;
border : 1px solid gray;
border-radius: 8px;
font-size : 16px;
}
.canvas {
display : none;
box-sizing: border-box;
position : fixed;
top : 0;
right : 0;
bottom : 0;
left : 0;
width : 100vw;
height : 100vh;
}
\ No newline at end of file
......@@ -10,18 +10,27 @@
</head>
<body>
<h2 class="h2">纯前端 JS :二维码:生成、扫描、识别 (HTML版)</h2>
<menu class="menu" id="menu">
<nav>二维码生成</nav> |
<nav class="active">二维码识别</nav>
</menu>
<h1 class="h1">纯前端 JS :二维码:生成、扫描、识别 (HTML版)</h1>
<hr />
<main class="reader">
<button class="sweep" onclick="sweep()">扫一扫</button>
<button class="sweep">
<input type="file" id="file" onchange="upload()" />从相册选择
</button>
<div class="imgurl">
<img id="imgurl" src="https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/github.com.png" alt="当前识别的二维码" />
<main class="main">
<div class="reader">
<button class="sweep" onclick="sweep()">扫一扫</button>
<button class="sweep">
<input type="file" id="file" onchange="upload()" />从相册选择
</button>
<div class="imgurl">
<img id="imgurl"
src="https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/github.com.png"
alt="当前识别的二维码" />
</div>
<textarea class="result" id="result" cols="32" rows="6" placeholder="二维码识别结果!"></textarea>
</div>
<textarea class="result" id="result" cols="32" rows="6" placeholder="二维码识别结果!"></textarea>
</main>
<canvas class="canvas" id="canvas"></canvas>
......@@ -31,22 +40,28 @@
<script src="./js/base.js"></script>
<script>
const result = document.querySelector('#result');
const QrCode = new QrCodeRecognition({
id: '#canvas',
seuccess: function (res) {
document.querySelector('#result').value = res.data;
},
sweepId: '#canvas', // 扫一扫
uploadId: '#file', // 从相册选择
error: function (err) {
document.querySelector('#result').value = err;
console.error(err);
// 识别错误反馈
result.value = err;
},
seuccess: function (res) {
// 识别成功反馈
result.value = res.data;
}
});
function sweep() {
QrCode.init();
result.value = '';
QrCode.sweep();
}
function upload() {
result.value = '';
QrCode.upload();
}
......
class QrCodeRecognition {
constructor(opts = {}) {
this.timer = null;
this.result = "";
this.isAnimation = true;
this.lineWidth = opts.borderWidth || 3;
this.strokeStyle = opts.lineColor || 'red';
this.audio = new Audio(opts.audio || './js/tone.mp3');
this.video = document.createElement('video');
this.cvsele = document.querySelector(opts.id);
this.canvas = this.cvsele.getContext('2d');
this.seuccess = opts.seuccess || Function;
this.error = opts.error || Function;
};
; (function (window, QrCodeRecognition) {
"use strict";
draw(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.strokeStyle;
this.canvas.stroke();
if (typeof define === 'function' && define.amd) {
define(QrCodeRecognition());
} else if (typeof exports === 'object') {
module.exports = QrCodeRecognition();
} else {
window.QrCodeRecognition = QrCodeRecognition();
};
sweep() {
if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
const { videoWidth, videoHeight } = this.video;
this.cvsele.width = videoWidth;
this.cvsele.height = videoHeight;
this.canvas.drawImage(this.video, 0, 0, videoWidth, videoHeight);
try {
const img = this.canvas.getImageData(0, 0, videoWidth, videoHeight);
document.querySelector('#imgurl').src = img;
const obj = jsQR(img.data, img.width, img.height, { inversionAttempts: 'dontInvert' });
if (obj) {
const loc = obj.location;
this.draw(loc.topLeftCorner, loc.topRightCorner);
this.draw(loc.topRightCorner, loc.bottomRightCorner);
this.draw(loc.bottomRightCorner, loc.bottomLeftCorner);
this.draw(loc.bottomLeftCorner, loc.topLeftCorner);
if (this.result != obj.data) {
this.audio.play();
this.seuccess(obj);
this.isAnimation = false;
cancelAnimationFrame(this.timer);
console.info("识别结果:", obj.data);
setTimeout(() => {
this.cvsele.style.display = "none";
}, 1000);
}
} else {
this.error("识别失败,请检查二维码是否正确!");
console.error("识别失败,请检查二维码是否正确!");
}
} catch (err) {
this.error(err);
console.error("识别失败,请检查二维码是否正确!", err);
};
}(typeof window !== "undefined" ? window : this, () => {
"use strict";
return class QrCodeRecognition {
constructor(opts = {}) {
this.timer = null;
this.result = "";
this.isAnimation = true;
this.lineWidth = opts.borderWidth || 3;
this.strokeStyle = opts.lineColor || 'red';
this.audio = new Audio(opts.audio || './js/tone.mp3');
this.video = document.createElement('video');
this.file = document.querySelector(opts.uploadId);
this.cvsele = document.querySelector(opts.sweepId);
this.canvas = this.cvsele.getContext('2d');
this.seuccess = opts.seuccess || Function;
this.error = opts.error || Function;
};
if (this.isAnimation) {
this.timer = requestAnimationFrame(() => {
this.sweep();
});
}
};
upload() {
const ele = document.querySelector('#file');
const file = ele.files[0];
const createObjectURL = window.createObjectURL || window.URL.createObjectURL || window.webkitURL.createObjectUR;
document.querySelector('#result').value = '';
draw(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.strokeStyle;
this.canvas.stroke();
};
cance() {
this.isAnimation = false;
cancelAnimationFrame(this.timer);
setTimeout(() => {
this.cvsele.style.display = "none";
}, 1000);
};
const fReader = new FileReader();
fReader.readAsDataURL(file); // Base64 8Bit字节码
// fReader.readAsBinaryString(file); // Binary 原始二进制
// fReader.readAsArrayBuffer(file); // ArrayBuffer 文件流
fReader.onload = (e) => {
document.querySelector('#imgurl').src = e.target.result || createObjectURL(file);
e.target.result && Jimp.read(e.target.result).then(async (res) => {
const { data, width, height } = res.bitmap;
untie() {
if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
const { videoWidth, videoHeight } = this.video;
this.cvsele.width = videoWidth;
this.cvsele.height = videoHeight;
this.canvas.drawImage(this.video, 0, 0, videoWidth, videoHeight);
try {
const resolve = await jsQR(data, width, height);
this.audio.play();
this.seuccess(resolve);
console.info("识别结果:", resolve.data);
const img = this.canvas.getImageData(0, 0, videoWidth, videoHeight);
document.querySelector('#imgurl').src = img;
const obj = jsQR(img.data, img.width, img.height, { inversionAttempts: 'dontInvert' });
if (obj) {
const loc = obj.location;
this.draw(loc.topLeftCorner, loc.topRightCorner);
this.draw(loc.topRightCorner, loc.bottomRightCorner);
this.draw(loc.bottomRightCorner, loc.bottomLeftCorner);
this.draw(loc.bottomLeftCorner, loc.topLeftCorner);
if (this.result != obj.data) {
this.audio.play();
this.cance();
this.seuccess(obj);
}
} else {
this.error("识别失败,请检查二维码是否正确!");
}
} catch (err) {
this.error("识别失败,请检查二维码是否正确!");
console.error("识别失败,请检查二维码是否正确!", err);
} finally {
console.info("读取到的文件:", res);
}
}).catch((err) => {
this.error("文件读取错误:", err);
console.error("文件读取错误:", err);
});
this.error("识别失败,请检查二维码是否正确!", err);
};
};
if (this.isAnimation) {
this.timer = requestAnimationFrame(() => {
this.untie();
});
}
};
};
init() {
this.isAnimation = true;
this.cvsele.style.display = "block";
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({
video: { facingMode: "environment" }
}).then(stream => {
this.video.srcObject = stream;
this.video.setAttribute('playsinline', true);
this.video.setAttribute('webkit-playsinline', true);
this.video.addEventListener('loadedmetadata', () => {
this.video.play();
this.sweep();
sweep() {
this.isAnimation = true;
this.cvsele.style.display = "block";
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({
video: { facingMode: "environment" }
}).then(stream => {
this.video.srcObject = stream;
this.video.setAttribute('playsinline', true);
this.video.setAttribute('webkit-playsinline', true);
this.video.addEventListener('loadedmetadata', () => {
this.video.play();
this.untie();
});
}).catch(error => {
console.error(error.name + "" + error.message + "" + error.constraint);
});
}).catch(error => {
console.error(error.name + "" + error.message + "" + error.constraint);
});
} else if (navigator.getUserMedia) {
navigator.getUserMedia({
video: { facingMode: "environment" }
}, (stream) => {
this.video.srcObject = stream;
this.video.setAttribute('playsinline', true);
this.video.setAttribute('webkit-playsinline', true);
this.video.addEventListener('loadedmetadata', () => {
this.video.play();
this.sweep();
} else if (navigator.getUserMedia) {
navigator.getUserMedia({
video: { facingMode: "environment" }
}, (stream) => {
this.video.srcObject = stream;
this.video.setAttribute('playsinline', true);
this.video.setAttribute('webkit-playsinline', true);
this.video.addEventListener('loadedmetadata', () => {
this.video.play();
this.untie();
});
}, (error) => {
console.error(error.name + "" + error.message + "" + error.constraint);
});
}, (error) => {
console.error(error.name + "" + error.message + "" + error.constraint);
});
} else {
if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
console.error('获取浏览器录音功能,因安全性问题,需要在localhost 或 127.0.0.1 或 https 下才能获取权限!');
} else {
alert('对不起:未识别到扫描设备!');
}
if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
console.error('获取浏览器录音功能,因安全性问题,需要在localhost 或 127.0.0.1 或 https 下才能获取权限!');
} else {
alert('对不起:未识别到扫描设备!');
}
};
};
upload() {
this.cance();
const file = this.file.files[0];
const createObjectURL = window.createObjectURL || window.URL.createObjectURL || window.webkitURL.createObjectUR;
const fReader = new FileReader();
fReader.readAsDataURL(file); // Base64 8Bit字节码
// fReader.readAsBinaryString(file); // Binary 原始二进制
// fReader.readAsArrayBuffer(file); // ArrayBuffer 文件流
fReader.onload = (e) => {
document.querySelector('#imgurl').src = e.target.result || createObjectURL(file);
e.target.result && Jimp.read(e.target.result).then(async (res) => {
const { data, width, height } = res.bitmap;
try {
const resolve = await jsQR(data, width, height);
this.audio.play();
this.seuccess(resolve);
} catch (err) {
this.error("识别失败,请检查二维码是否正确!", err);
} finally {
console.info("读取到的文件:", res);
}
}).catch((err) => {
this.error("文件读取错误:", err);
});
};
};
}
};
\ No newline at end of file
};
}));
\ No newline at end of file
......@@ -2,16 +2,30 @@
GitHub:[https://github.com/MuGuiLin/QRCode](https://github.com/MuGuiLin/QRCode)
### 纯前端 HTML / Vue :二维码:生成、扫描、识别
### 纯前端 HTML / Vue :二维码:生成、扫描、识别、解析、扫一扫
> 该Demo功能共分为:HTML版 和 Vue版 两个版本!
>
> 不依赖任何关于微信环境、微信JS-SDK,微信受权等!
>
> 支持二维码生成,实时动态生成和渲染!
>
> 支持扫一扫识别,从相册选择二维码识别!
>
> 支持PC端,手机移动端等!
### HTML版 Demo实例效果:
![二维码识别](https://raw.githubusercontent.com/MuGuiLin/QRCode/master/HtmlQRCode/img/qrcode.png)
### Vue.js版 Demo实例效果:
![二维生成](https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/create.png)
![二维生成](https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/create.png)
------
![二维生成](https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/qrcode.png)
\ No newline at end of file
![二维码识别](https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/qrcode.png)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册