Use html5-qrcode instead of @zxing/library directly for label scanner.

This improves the usability a bit
This commit is contained in:
Jan Böhmer 2022-08-13 22:41:54 +02:00
parent f98487a03b
commit ca5823819d
4 changed files with 57 additions and 113 deletions

View file

@ -1,86 +1,51 @@
import {Controller} from "@hotwired/stimulus";
import * as ZXing from "@zxing/library";
//import * as ZXing from "@zxing/library";
import {Html5QrcodeScanner, Html5Qrcode} from "html5-qrcode";
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = [ "source" ]
//codeReader = null;
_scanner = null;
codeReader = null;
connect() {
console.log('Init Scanner');
this.codeReader = new ZXing.BrowserMultiFormatReader();
this.initScanner();
//This function ensures, that the qrbox is 70% of the total viewport
let qrboxFunction = function(viewfinderWidth, viewfinderHeight) {
let minEdgePercentage = 0.7; // 70%
let minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight);
let qrboxSize = Math.floor(minEdgeSize * minEdgePercentage);
return {
width: qrboxSize,
height: qrboxSize
};
}
//Try to get the number of cameras. If the number is 0, then the promise will fail, and we show the warning dialog
Html5Qrcode.getCameras().catch((devices) => {
document.getElementById('scanner-warning').classList.remove('d-none');
});
this._scanner = new Html5QrcodeScanner(this.element.id, {
fps: 2,
qrbox: qrboxFunction,
experimentalFeatures: {
//This option improves reading quality on android chrome
useBarCodeDetectorIfSupported: true
}
}, false);
this._scanner.render(this.onScanSuccess.bind(this));
}
codeScannedHandler(result, err) {
if (result) {
//@ts-ignore
document.getElementById('scan_dialog_input').value = result.text;
//Submit form
//@ts-ignore
document.getElementById('scan_dialog_form').submit();
}
if (err && !(err instanceof ZXing.NotFoundException)) {
console.error(err);
//document.getElementById('result').textContent = err
}
}
initScanner() {
let selectedDeviceId;
this.codeReader.listVideoInputDevices()
.then((videoInputDevices) => {
if (videoInputDevices.length >= 1) {
const sourceSelect = document.getElementById('sourceSelect');
videoInputDevices.forEach((element) => {
const sourceOption = document.createElement('option');
sourceOption.text = element.label;
sourceOption.value = element.deviceId;
sourceSelect.appendChild(sourceOption);
});
//Try to retrieve last selected webcam...
let last_cam_id = localStorage.getItem('scanner_last_cam_id');
if (!!last_cam_id) {
//selectedDeviceId = localStorage.getItem('scanner_last_cam_id');
sourceSelect.value = last_cam_id;
} else {
selectedDeviceId = videoInputDevices[0].deviceId;
}
sourceSelect.onchange = () => {
//@ts-ignore
selectedDeviceId = sourceSelect.value;
localStorage.setItem('scanner_last_cam_id', selectedDeviceId);
changeHandler();
};
document.getElementById('sourceSelectPanel').classList.remove('d-none');
document.getElementById('video').classList.remove('d-none');
document.getElementById('scanner-warning').classList.add('d-none');
}
let changeHandler = () => {
this.codeReader.reset();
this.codeReader.decodeFromVideoDevice(selectedDeviceId, 'video', (result, err) => this.codeScannedHandler(result, err));
console.log(`Started continous decode from camera with id ${selectedDeviceId}`)
};
//Register Change Src Button
//document.getElementById('changeSrcBtn').addEventListener('click', changeHandler);
//Try to start logging automatically.
changeHandler();
})
.catch((err) => {
console.error(err)
})
onScanSuccess(decodedText, decodedResult) {
//Put our decoded Text into the input box
document.getElementById('scan_dialog_input').value = decodedText;
//Submit form
document.getElementById('scan_dialog_form').submit();
}
}

View file

@ -57,7 +57,6 @@
"@ckeditor/ckeditor5-watchdog": "^35.0.0",
"@ckeditor/ckeditor5-word-count": "^35.0.0",
"@jbtronics/bs-treeview": "^1.0.1",
"@zxing/library": "^0.19.1",
"bootbox": "^5.4.0",
"bootstrap-select": "v1.14.0-beta3",
"bootswatch": "^5.1.3",
@ -76,6 +75,7 @@
"dompurify": "^2.0.6",
"emoji.json": "^13.1.0",
"exports-loader": "^3.0.0",
"html5-qrcode": "^2.2.1",
"jszip": "^3.2.0",
"katex": "^0.16.0",
"marked": "^4.0.3",

View file

@ -3,31 +3,24 @@
{% block card_title %}<i class="fas fa-camera-retro fa-fw"></i> {% trans %}label_scanner.title{% endtrans %}{% endblock %}
{% block card_content %}
<div class="alert alert-warning" id="scanner-warning">
<div class="alert alert-warning d-none" id="scanner-warning">
<strong>{% trans %}label_scanner.no_cam_found.title{% endtrans %}</strong>: {% trans %}label_scanner.no_cam_found.text{% endtrans %}
</div>
<div class="">
<div class="form-group row">
<div class="offset-sm-3 col-sm-9">
<div class="img-thumbnail" style="max-width: 600px;">
<div id="reader-box" {{ stimulus_controller('pages/barcode_scan') }}></div>
</div>
</div>
</div>
</div>
{{ form_start(form, {'attr': {'id': 'scan_dialog_form'}}) }}
{{ form_end(form) }}
<div class="">
<div class="form-group row">
<div class="offset-sm-3 col-sm-9">
<video id="video" width="100%" height="auto" class="scanner-video img-thumbnail d-none" {{ stimulus_controller('pages/barcode_scan') }}>
</video>
</div>
</div>
{# <div>
<button type="button" class="btn btn-secondary" id="changeSrcBtn">Change Source</button>
</div>#}
<div id="sourceSelectPanel" class="form-group row d-none">
<label for="sourceSelect" class="col-sm-3 col-form-label">{% trans %}label_scanner.source_select{% endtrans %}</label>
<div class="col-sm-9">
<select id="sourceSelect" style="" class="form-control"></select>
</div>
</div>
</div>
{% endblock %}

View file

@ -1830,20 +1830,6 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
"@zxing/library@^0.19.1":
version "0.19.1"
resolved "https://registry.yarnpkg.com/@zxing/library/-/library-0.19.1.tgz#68932436a9cf860e2148a6d6ae38fe1e27ea23a8"
integrity sha512-rKwvl3Uuqs8yf364iU9l3HDDaIx8yPv+CH6DbtQaQr67VdKLG22G1ukEp9fOdDefE6tpLtRAdMnTrgtpiaKAZw==
dependencies:
ts-custom-error "^3.0.0"
optionalDependencies:
"@zxing/text-encoding" "~0.9.0"
"@zxing/text-encoding@~0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b"
integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==
abab@^2.0.3, abab@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
@ -3787,6 +3773,11 @@ html-entities@^2.3.2:
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
html5-qrcode@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/html5-qrcode/-/html5-qrcode-2.2.1.tgz#7492359f872abf4ae72ab43824c572ee53607999"
integrity sha512-itYnSlSxC3gNRe825mUkKaMzlmevLc4hpH2XLlhCdiEYIE3aMdQUr1XjQ9/zk7NuRMcYRerlbCaMKM+Z66KpSg==
htmlparser2@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@ -6119,11 +6110,6 @@ tr46@^2.1.0:
dependencies:
punycode "^2.1.1"
ts-custom-error@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.2.0.tgz#ff8f80a3812bab9dc448536312da52dce1b720fb"
integrity sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A==
ts-loader@^9.2.6, ts-loader@^9.3.0:
version "9.3.1"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.1.tgz#fe25cca56e3e71c1087fe48dc67f4df8c59b22d4"