diff --git a/addons/web/static/src/webclient/barcode/ZXingBarcodeDetector.js b/addons/web/static/src/webclient/barcode/ZXingBarcodeDetector.js index d68281b6b59..b1952130d62 100644 --- a/addons/web/static/src/webclient/barcode/ZXingBarcodeDetector.js +++ b/addons/web/static/src/webclient/barcode/ZXingBarcodeDetector.js @@ -66,12 +66,34 @@ export function buildZXingBarcodeDetector(ZXing) { throw new DOMException("HTMLVideoElement is not ready", "InvalidStateError"); } const canvas = document.createElement("canvas"); + + let barcodeArea; + if (this.cropArea && (this.cropArea.x || this.cropArea.y)) { + barcodeArea = this.cropArea; + } else { + barcodeArea = { + x: 0, + y: 0, + width: video.videoWidth, + height: video.videoHeight, + }; + } + canvas.width = barcodeArea.width; + canvas.height = barcodeArea.height; + const ctx = canvas.getContext("2d"); - canvas.width = video.videoWidth; - canvas.height = video.videoHeight; - - ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); + ctx.drawImage( + video, + barcodeArea.x, + barcodeArea.y, + barcodeArea.width, + barcodeArea.height, + 0, + 0, + barcodeArea.width, + barcodeArea.height + ); const luminanceSource = new ZXing.HTMLCanvasElementLuminanceSource(canvas); const binaryBitmap = new ZXing.BinaryBitmap(new ZXing.HybridBinarizer(luminanceSource)); @@ -104,6 +126,10 @@ export function buildZXingBarcodeDetector(ZXing) { throw err; } } + + setCropArea(cropArea) { + this.cropArea = cropArea; + } } /** diff --git a/addons/web/static/src/webclient/barcode/barcode_scanner.js b/addons/web/static/src/webclient/barcode/barcode_scanner.js index 8da814e966e..752deef1ed3 100644 --- a/addons/web/static/src/webclient/barcode/barcode_scanner.js +++ b/addons/web/static/src/webclient/barcode/barcode_scanner.js @@ -95,6 +95,10 @@ export class BarcodeDialog extends Component { }); } + isZXingBarcodeDetector() { + return this.detector && this.detector.__proto__.constructor.name === "ZXingBarcodeDetector"; + } + /** * Check for camera preview element readiness * @@ -113,6 +117,11 @@ export class BarcodeDialog extends Component { onResize(overlayInfo) { this.overlayInfo = overlayInfo; + if (this.isZXingBarcodeDetector()) { + // TODO need refactoring when ZXing will support multiple result in one scan + // https://github.com/zxing-js/library/issues/346 + this.detector.setCropArea(this.adaptValuesWithRatio(this.overlayInfo, true)); + } } /** @@ -142,12 +151,8 @@ export class BarcodeDialog extends Component { try { const codes = await this.detector.detect(this.videoPreviewRef.el); for (const code of codes) { - let { x, y, width, height } = code.boundingBox; - x *= this.zoomRatio; - y *= this.zoomRatio; - width *= this.zoomRatio; - height *= this.zoomRatio; - if (this.overlayInfo.x && this.overlayInfo.y) { + if (!this.isZXingBarcodeDetector() && this.overlayInfo.x && this.overlayInfo.y) { + const { x, y, width, height } = this.adaptValuesWithRatio(code.boundingBox); if ( x < this.overlayInfo.x || x + width > this.overlayInfo.x + this.overlayInfo.width || @@ -164,6 +169,18 @@ export class BarcodeDialog extends Component { this.onError(err); } } + + adaptValuesWithRatio(object, dividerRatio = false) { + const newObject = Object.assign({}, object); + for (const key of Object.keys(newObject)) { + if (dividerRatio) { + newObject[key] /= this.zoomRatio; + } else { + newObject[key] *= this.zoomRatio; + } + } + return newObject; + } } Object.assign(BarcodeDialog, {