В продолжение моего предыдущего поста про JS-сканнеры штрихкодов. Примерно в течении года я использовал EddieLa BarcodeReader. Со склада, где проходили испытания, сообщили о медленной работе и частых ошибочных результатах. Поэтому поиски продолжились.
В комментариях к предыдущей статье было озвучено две полезных мысли:
- Библиотеку ZBar можно скомпилировать в Wasm, и что она работает хорошо.
- Я пропустил библиотеку ZXing, которая тоже работает хорошо.
Для ZBar после компиляции потребуется писать какую-то обёртку, а значит разбираться в её коде. Для интеграции ZXing в свой проект уже всё готово и я начал с неё. Забегаю вперёд, скажу, что библиотека работает великолепно — намного быстрее и точнее. Мои коллеги в восторге.
Итак, проект библиотеки (GitHub). Живой пример. Поддерживаемые типы кодов:
- EAN8
- EAN13
- Code39
- Code128
- ITF
- RSS-14
- QR Code
- Data Matrix
- PDF 417
Использование
Самый простой набор действий такой. Сначала подключаем JS-модуль библиотеки. Можно использовать CDN-ссылку, можно скачать к себе:
<script type="text/javascript" src="https://unpkg.com/@zxing/library@latest"></script>
Далее добавляем на страничку компонент, в который будет выводиться видопоток:
<video id="video" ></video>
Далее добавляем JS-скрипт:
const codeReader = new ZXing.BrowserMultiFormatReader();
g_codeReader.decodeFromVideoDevice(cameraId, 'video', (result, err) => {
if (result) {
alert(result.text);
}
if (err && !(err instanceof ZXing.NotFoundException)) {
alert(err);
}
});
Здесь:
- cameraId — это УИД камеры, с которой будет поступать видеопоток.
- "video" — это ID компонента на страничке, куда будет выводиться видеопоток.
- result.text — содержит отсканированный код.
- err — содержит текст ошибки. Как мы видим — всё достаточно просто.
Как определить cameraId
Логично иметь отдельную страницу с настройками. Там и нужно выводить список имеющихся на устройстве камер. Пользователь выбирает, какая его интересует и сохраняет настройки. Можно хранить в куках.
Вариант 1
function settings_onload() {
if (!navigator.mediaDevices
|| !navigator.mediaDevices.enumerateDevices) {
alert("enumerateDevices() not supported.");
return;
}
try {
navigator.mediaDevices.enumerateDevices()
.then(settings_create_cameras_radiobutton);
}catch(err){
alert(err.name + ": " + err.message);
}
}
function settings_create_cameras_radiobutton(devices) {
for (var n = 0; n < devices.length; n++) {
device = devices[n];
if (device.kind == 'videoinput') {
settings_add_camera_case(
device.label
,device.deviceId
);
}
}
}
Здесь функция "settings_add_camera_case" реализует добавление элемента списка камер. Первый аргумент — это название камеры, а второй — как раз её УИД.
Вариант 2
Также можно воспользоваться средствами компоненты:
codeReader.getVideoInputDevices()
.then((videoInputDevices) => {
const sourceSelect = document.getElementById('sourceSelect');
selectedDeviceId = videoInputDevices[0].deviceId;
if (videoInputDevices.length >= 1) {
videoInputDevices.forEach((element) => {
const sourceOption = document.createElement('option');
sourceOption.text = element.label;
sourceOption.value = element.deviceId;
sourceSelect.appendChild(sourceOption);
});
}
}
Звук "Бип"
При успешном срабатывании можно добавить классический звук "Бип":
var beep = new Audio();
beep.addEventListener('loadeddata', function() { beep.play(); });
beep.src = beepUrl;
Где beepUrl — это адрес к файлику со звуком.
Собственно всё.