客戶有一個需求是想要用手機掃描Qrcode
但是他們給過來的code是黑底白色的且寬度小於一公分
目前是使用了html5-qrcode的技術
調便了各種參數還是無法使用...
也問過ChatGPT
給出的建議都也試遍了還是無法 QQ
想問各位大前輩
有沒有人解決過這樣的需求?
請指點小的一點方向~~~TAT
目前我的code:
HTML--->
<script src="https://reeteshghimire.com.np/wp-content/uploads/2021/05/html5-qrcode.min_.js"></script>
<div class="row">
<div class="col">
<div style="width:300px;" id="reader"></div>
</div>
<div class="col" style="padding:30px;">
<h4>SCAN RESULT</h4>
<div id="result">Result Here</div>
</div>
</div>
CSS--->
.result{
background-color: green;
color:#fff;
padding:20px;
}
.row{
display:flex;
}
JS--->
function onScanSuccess(qrCodeMessage) {
document.getElementById('result').innerHTML = '<span class="result">'+qrCodeMessage+'</span>';
}
function onScanError(errorMessage) {
//handle scan error
}
var html5QrcodeScanner = new Html5QrcodeScanner(
"reader", {
fps: 10,//讀取速度
qrbox: 50,//qrcode掃瞄區大小
resolution: 1024,//解析度
scale: 5.0,//啟用等比縮放
area: 0.3,//擴展QR code的區域
findLight: true,//尋找光點
colorInvert: true,//色彩反轉
angle: -90,//設置掃描視角
minimumBlur: 0.01,//最小模糊程度
readers: ["code_128_reader", "ean_reader"],//解碼器
aspectRatio: 1,//設定鏡頭的寬高比
cameraIdOrConfig: {
facingMode: "environment",
zoom: 3.0
}//設定鏡頭的縮放比例
}
);
html5QrcodeScanner.render(onScanSuccess, onScanError);
我測試了一下,包含:
都無法掃描出反白的 QR Code
我想這一步要先解決,才要擔心圖片太小的問題
做了一個測試用的QR Code 頁面
螢幕上左右各有正常與反白的 QR Code 可以測試
PS. 我直接用 firefox 內建的掃描是可以掃出反白的 QR Code 的
2023-03-29 更新
後來發現 https://github.com/nimiq/qr-scanner 有支援反白
使用上也滿方便的,是我目前最佳的解法
html5-qrocde 的 issue#94 有人提到 https://github.com/cozmo/jsQR 可以掃反白
jsQR 的說明也有寫到預設是開啟的,只是它 Demo 把這功能關閉了
(我猜是效能的關係)
下面程式碼我測試過,可以掃出反白
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<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>鏡頭測試</title>
<!-- npm install jsqr -->
<script src="./node_modules/jsqr/dist/jsQR.js"></script>
</head>
<body>
<button id="start">開始</button>
<button id="stop">停止</button>
<p></p>
<hr>
<canvas></canvas>
<script type="module">
import Camera from './camera.js';
// 相機
const cam = new Camera(document.querySelector('canvas'));
// 顯示掃出來的結果
const logP = document.querySelector('p');
// 開始按鈕
document.querySelector('#start').addEventListener('click', ()=>{
cam.start();
cam.onNextFrame = readQrCode;
logP.textContent = '掃描結果: 無';
});
// 停止按鈕
document.querySelector('#stop').addEventListener('click', ()=>{
cam.stop();
});
function readQrCode(data) {
const code = jsQR(data.data, data.width, data.height);
if(code) {
logP.textContent = `掃描結果: ${code.data}`;
}
cam.onNextFrame = readQrCode;
}
</script>
</body>
</html>
camera.js
(稍微包裝一下鏡頭的處理)
export default class Camera {
/**
* constructor
* @param {canvasElement} canvasElement 鏡頭開啟時,會繪製在這邊
*/
constructor(canvasElement) {
this.canvas = canvasElement;
this.video = document.createElement("video");
this.video.srcObject = null;
this.resizeFlag = false;
/**
* @var {callback} 透過設定 onNextFrame 可以捕捉到下一個畫面
* 捕捉到後呼叫此函數,並且 onNextFrame 會被設定為 null
*/
this.onNextFrame = null;
}
/**
* 開啟鏡頭(瀏覽器會跳出要求權限)
* (開啟後可以透過設定 onNextFrame 捕捉畫面)
*/
start() {
// 已經啟動
if (this.video.srcObject) {
return;
}
// Use facingMode: environment to attemt to get the front camera on phones
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then((stream) => {
this.video.srcObject = stream;
this.video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
this.video.play();
this.resizeFlag = true;
requestAnimationFrame(this._tick.bind(this));
});
}
/**
* 停止使用鏡頭
*/
stop() {
if (this.video.srcObject) {
const tracks = this.video.srcObject.getTracks();
tracks.forEach(function (track) {
track.stop();
});
this.video.srcObject = null;
}
}
_tick() {
const video = this.video;
if (video.readyState === video.HAVE_ENOUGH_DATA) {
const canvas = this.canvas;
const ctx = canvas.getContext('2d');
if (this.resizeFlag) {
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
this.resizeFlag = false;
}
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
if (this.onNextFrame) {
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let callback = this.onNextFrame;
this.onNextFrame = null;
callback(imageData);
}
}
requestAnimationFrame(this._tick.bind(this));
}
}
效能部分你可以再調整看看
例如 jsQR 可以移到 web worker 去跑
我後來發現另外一個更好用的
https://github.com/nimiq/qr-scanner
qr-scanner 可以~~~(灑花)
謝謝前輩 :D