文章介绍
这里使用了jsQR和zxing两种方式,分别在普通的H5和vue中使用,文章附上完整demo和一些注意事项
注意事项
这里H5也好,vue也好,如果想要部署到服务器上,需要用https协议,否则无法使用。本地启动项目的时候,很多人在vue中无法实现该效果,那是因为需要我们从localhost路径打开,否则也无法使用摄像头
vue 或 H5,使用jsQR
使用jsQR这个JS库
这里附上这个库的地址:https://s3.gendome.net/activity/js/jsQR.js
先把上面这个JS文件下载下来,比如我这里命名为jsQR.js,使用我这样的写法
H5中
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
<script src="./jsQR.js"></script>
</head>
<body>
<video style="display: none;" id="video"></video>
<canvas style="width: 100%; height: 100%;" id="canvas"></canvas>
<canvas style="display: none;" id="2d"></canvas>
</body>
<script type="text/javascript">
var video = document.createElement("video");
var canvasElement = document.getElementById("canvas");
var canvas = canvasElement.getContext("2d");
// 尝试打开手机上安装后置摄像头
navigator.mediaDevices.getUserMedia({
video: { facingMode: "environment" }
}).then(function (stream) {
video.srcObject = stream;
// 阻止IOS视频全屏
video.setAttribute("playsinline", true);
video.play();
requestAnimationFrame(tick);
});
function tick() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
canvasElement.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
// QR码解析
var code = jsQR(
imageData.data, // 图像数据
imageData.width, // 宽度
imageData.height, // 高度
{
inversionAttempts: "dontInvert",
}
);
if (code) {
console.log(code.data);
}
}
requestAnimationFrame(tick);
}
</script>
</html>
vue中
<template>
<div>
<video style="display: none" id="video"></video>
<canvas style="width: 100vw; margin-top: 13vw" id="canvas"></canvas>
<canvas style="display: none" id="2d"></canvas>
</div>
</template>
<script setup>
import { ref, onMounted} from "vue";
import "@/utils/jsQR.js"; // 添加关闭摄像头的函数
const stopMediaTracks = () => {
if (streams) {
streams.getTracks().forEach((track) => track.stop());
}
video.srcObject = null;
};
const streams = ref(null); // 初始化 stream 变量
onMounted(() => {
var video = document.createElement("video");
var canvasElement = document.getElementById("canvas");
var canvas = canvasElement.getContext("2d");
console.log(navigator.mediaDevices);
// 尝试打开手机上安装后置摄像头
navigator.mediaDevices
.getUserMedia({
video: { facingMode: "environment" },
})
.then(function (stream) {
streams.value = stream;
video.srcObject = stream;
// 阻止IOS视频全屏
video.setAttribute("playsinline", true);
video.play();
requestAnimationFrame(tick);
});
function tick() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
canvasElement.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
var imageData = canvas.getImageData(
0,
0,
canvasElement.width,
canvasElement.height
);
// QR码解析
var code = jsQR(
imageData.data, // 图像数据
imageData.width, // 宽度
imageData.height, // 高度
{
inversionAttempts: "dontInvert",
}
);
if (code) {
console.log(code.data);
alert(code.data);
}
}
requestAnimationFrame(tick);
}
});
</script>