scandit-sdk
Version:
Scandit Barcode Scanner SDK for the Web
1,244 lines (1,135 loc) • 61.3 kB
text/typescript
import { EventEmitter, ListenerFn } from "eventemitter3";
import { Howl, Howler } from "howler/dist/howler.core.min.js";
import { beepSound } from "./assets/base64assets";
import { userLicenseKey } from "../index";
import { BarcodePickerCameraManager } from "./barcodePickerCameraManager";
import { BarcodePickerGui } from "./barcodePickerGui";
import { BrowserCompatibility } from "./browserCompatibility";
import { BrowserHelper } from "./browserHelper";
import { Camera } from "./camera";
import { CameraManager } from "./cameraManager";
import { CameraSettings } from "./cameraSettings";
import { CustomError } from "./customError";
import { DummyCameraManager } from "./dummyCameraManager";
import { ImageSettings } from "./imageSettings";
import { Parser } from "./parser";
import { Scanner } from "./scanner";
import { ScanResult } from "./scanResult";
import { ScanSettings } from "./scanSettings";
import { SearchArea } from "./searchArea";
import { UnsupportedBrowserError } from "./unsupportedBrowserError";
/**
* @hidden
*/
type EventName = "ready" | "submitFrame" | "processFrame" | "scan" | "scanError";
/**
* @hidden
*/
class BarcodePickerEventEmitter extends EventEmitter<EventName> {}
/**
* A barcode picker element used to get and show camera input and perform scanning operations.
*
* The barcode picker will automatically fit and scale inside the given *originElement*.
*
* Each barcode picker internally contains a [[Scanner]] object with its own WebWorker thread running a
* separate copy of the external Scandit Engine library. To optimize loading times and performance it's
* recommended to reuse the same picker and to already create the picker in advance (hidden) and just
* display it when needed whenever possible.
*
* As the loading of the external Scandit Engine library can take some time the picker always starts inactive
* (but showing GUI and video) and then activates, if not paused, as soon as the library is ready to scan.
* The [[on]] method targeting the [[ready]] event can be used to set up a listener function to be called when the
* library is loaded.
*
* The picker can also operate in "single image mode", letting the user click/tap to take a single image to be scanned
* via the camera (mobile/tablet) or a file select dialog (desktop). This is provided automatically as fallback by
* default when the OS/browser only supports part of the needed features and cannot provide direct access to the camera
* for video streaming and continuous scanning, or can also be forced. This behaviour can be set up on creation. Note
* that in this mode some of the functions provided by the picker will have no effect.
*
* By default an alert is shown if an internal error during scanning is encountered which prevents the scanning
* procedure from continuing when running on a local IP address. As this uses the built-in [[scanError]] event
* functionality, if unwanted it can be disabled by calling [[removeAllListeners]] on the BarcodePicker
* instance (right after creation).
*
* You are not allowed to hide the Scandit logo present in the corner of the GUI.
*/
export class BarcodePicker {
private readonly cameraManager: CameraManager;
private readonly barcodePickerGui: BarcodePickerGui;
private readonly eventEmitter: BarcodePickerEventEmitter;
private readonly scanner: Scanner;
private readonly beepSound: Howl;
private readonly vibrateFunction: (pattern: number | number[]) => boolean;
private readonly scannerReadyEventListener: () => void;
private playSoundOnScan: boolean;
private vibrateOnScan: boolean;
private scanningPaused: boolean;
private fatalError: Error;
private latestVideoTimeProcessed: number;
private destroyed: boolean;
private isReadyToWork: boolean;
private cameraAccess: boolean;
private targetScanningFPS: number;
private averageProcessingTime: number;
private constructor(
originElement: HTMLElement,
{
visible,
singleImageMode,
playSoundOnScan,
vibrateOnScan,
scanningPaused,
guiStyle,
videoFit,
laserArea,
viewfinderArea,
scanner,
scanSettings,
targetScanningFPS,
hideLogo
}: {
visible: boolean;
singleImageMode: boolean;
playSoundOnScan: boolean;
vibrateOnScan: boolean;
scanningPaused: boolean;
guiStyle: BarcodePicker.GuiStyle;
videoFit: BarcodePicker.ObjectFit;
laserArea?: SearchArea;
viewfinderArea?: SearchArea;
scanner?: Scanner;
scanSettings: ScanSettings;
targetScanningFPS: number;
hideLogo: boolean;
}
) {
this.isReadyToWork = false;
this.destroyed = false;
this.scanningPaused = scanningPaused;
Howler.autoSuspend = false;
this.beepSound = new Howl({
src: beepSound
});
// istanbul ignore else
if (navigator.vibrate != null) {
this.vibrateFunction = navigator.vibrate;
} else if (navigator.webkitVibrate != null) {
this.vibrateFunction = navigator.webkitVibrate;
} else if (navigator.mozVibrate != null) {
this.vibrateFunction = navigator.mozVibrate;
} else if (navigator.msVibrate != null) {
this.vibrateFunction = navigator.msVibrate;
}
this.eventEmitter = new EventEmitter();
this.setPlaySoundOnScanEnabled(playSoundOnScan);
this.setVibrateOnScanEnabled(vibrateOnScan);
this.setTargetScanningFPS(targetScanningFPS);
if (scanner == null) {
this.scanner = new Scanner({ scanSettings });
} else {
this.scanner = scanner;
this.scanner.applyScanSettings(scanSettings);
}
this.scannerReadyEventListener = this.handleScannerReady.bind(this);
this.scanner.on("ready", this.scannerReadyEventListener);
this.barcodePickerGui = new BarcodePickerGui({
scanner: this.scanner,
originElement,
singleImageMode,
scanningPaused,
visible,
guiStyle,
videoFit,
hideLogo,
laserArea,
viewfinderArea,
cameraUploadCallback: this.processVideoFrame.bind(this, true)
});
if (singleImageMode) {
this.cameraManager = new DummyCameraManager();
} else {
this.cameraManager = new BarcodePickerCameraManager(this.triggerFatalError.bind(this), this.barcodePickerGui);
this.scheduleVideoProcessing();
}
this.barcodePickerGui.setCameraManager(this.cameraManager);
}
/**
* Create a [[BarcodePicker]] instance, creating the needed HTML in the given origin element.
* If the *accessCamera* option is enabled (active by default) and the picker is not in "single image mode",
* the available cameras are accessed and camera access permission is requested to the user if needed.
* This object expects that at least a camera is available. The active camera is accessed and kept active during the
* lifetime of the picker (also when hidden or scanning is paused), and is only released when [[destroy]] is called.
*
* It is required to having configured the library via [[configure]] before this object can be created.
*
* The "single image mode" behaviour of the picker can be set up via the
* *singleImageMode* option, which accepts a configuration object of the form:
* ```
* {
* desktop: {
* always: false, allowFallback: true
* },
* mobile: {
* always: false, allowFallback: true
* }
* }
* ```
*
* Depending on parameters, device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `LibraryNotConfiguredError`
* - `NoOriginElementError`
* - `UnsupportedBrowserError`
* - `PermissionDeniedError`
* - `NotAllowedError`
* - `NotFoundError`
* - `AbortError`
* - `NotReadableError`
* - `InternalError`
* - `NoCameraAvailableError`
*
* @param originElement The HTMLElement inside which all the necessary elements for the picker will be added.
* @param visible <div class="tsd-signature-symbol">Default = true</div>
* Whether the picker starts in a visible state.
* @param singleImageMode <div class="tsd-signature-symbol">Default =
* { desktop: { always: false, allowFallback: true }, mobile: { always: false, allowFallback: true } }</div>
* Whether to provide a UI to pick/snap a single image from the camera instead of accessing and using the persistent
* video stream from a camera ("force"), or to allow to provide this as a fallback ("allowFallback") in case the
* necessary features for direct camera access are not provided by the OS/browser.
* @param playSoundOnScan <div class="tsd-signature-symbol">Default = false</div>
* Whether a sound is played on barcode recognition (iOS requires user input).
* @param vibrateOnScan <div class="tsd-signature-symbol">Default = false</div>
* Whether the device vibrates on barcode recognition (only Chrome & Firefox, requires user input).
* @param scanningPaused <div class="tsd-signature-symbol">Default = false</div>
* Whether the picker starts in a paused scanning state.
* @param guiStyle <div class="tsd-signature-symbol">Default = GuiStyle.LASER</div>
* The GUI style for the picker.
* @param videoFit <div class="tsd-signature-symbol">Default = ObjectFit.CONTAIN</div>
* The fit type for the video element of the picker.
* @param laserArea <div class="tsd-signature-symbol">Default = undefined</div>
* The area of the laser displayed when the GUI style is set to *laser* (the laser will match the width and be
* vertically centered), by default the area will match the current [[ScanSettings]]'s *searchArea* option.
* @param viewfinderArea <div class="tsd-signature-symbol">Default = undefined</div>
* The area of the viewfinder displayed when the GUI style is set to *viewfinder*, by default the area will match
* the current [[ScanSettings]]'s *searchArea* option.
* @param enableCameraSwitcher <div class="tsd-signature-symbol">Default = true</div>
* Whether to show a GUI button to switch between different cameras (when available).
* @param enableTorchToggle <div class="tsd-signature-symbol">Default = true</div>
* Whether to show a GUI button to toggle device torch on/off (when available, only Chrome).
* @param enableTapToFocus <div class="tsd-signature-symbol">Default = true</div>
* Whether to trigger a manual focus of the camera when clicking/tapping on the video (when available, only Chrome).
* @param enablePinchToZoom <div class="tsd-signature-symbol">Default = true</div>
* Whether to control the zoom of the camera when doing a pinching gesture on the video (when available, only Chrome).
* @param accessCamera <div class="tsd-signature-symbol">Default = true</div>
* Whether to immediately access the camera (and requesting user permissions if needed) on picker creation.
* @param camera <div class="tsd-signature-symbol">Default = undefined</div>
* The camera to be used for video input, if not specified the back or only camera will be used.
* @param cameraSettings <div class="tsd-signature-symbol">Default = undefined</div>
* The camera options used when accessing the camera, by default HD resolution is used.
* @param scanner <div class="tsd-signature-symbol">Default = undefined</div>
* The scanner object responsible for scanning via the external Scandit Engine library
* (a new scanner will be created and initialized if not provided).
* @param scanSettings <div class="tsd-signature-symbol">Default = new ScanSettings()</div>
* The configuration object for scanning options to be applied to the scanner (all symbologies disabled by default).
* @param targetScanningFPS <div class="tsd-signature-symbol">Default = 30</div>
* The target frames per second to be processed, the final speed is limited by the camera framerate (usually 30 FPS)
* and the frame processing time of the device. By setting this to lower numbers devices can save power by performing
* less work during scanning operations, depending on device speed (faster devices can "sleep" for longer periods).
* Must be a number bigger than 0.
* @returns A promise resolving to the created ready [[BarcodePicker]] object.
*/
public static create(
originElement: HTMLElement,
{
visible = true,
singleImageMode = {
desktop: { always: false, allowFallback: true },
mobile: { always: false, allowFallback: true }
},
playSoundOnScan = false,
vibrateOnScan = false,
scanningPaused = false,
guiStyle = BarcodePicker.GuiStyle.LASER,
videoFit = BarcodePicker.ObjectFit.CONTAIN,
laserArea,
viewfinderArea,
scanner,
scanSettings = new ScanSettings(),
enableCameraSwitcher = true,
enableTorchToggle = true,
enableTapToFocus = true,
enablePinchToZoom = true,
accessCamera = true,
camera,
cameraSettings,
targetScanningFPS = 30
}: {
visible?: boolean;
singleImageMode?: {
desktop: { always: boolean; allowFallback: boolean };
mobile: { always: boolean; allowFallback: boolean };
};
playSoundOnScan?: boolean;
vibrateOnScan?: boolean;
scanningPaused?: boolean;
guiStyle?: BarcodePicker.GuiStyle;
videoFit?: BarcodePicker.ObjectFit;
laserArea?: SearchArea;
viewfinderArea?: SearchArea;
scanner?: Scanner;
scanSettings?: ScanSettings;
enableCameraSwitcher?: boolean;
enableTorchToggle?: boolean;
enableTapToFocus?: boolean;
enablePinchToZoom?: boolean;
accessCamera?: boolean;
camera?: Camera;
cameraSettings?: CameraSettings;
targetScanningFPS?: number;
} = {}
): Promise<BarcodePicker> {
let singleImageModeForced: boolean;
let singleImageModeFallbackAllowed: boolean;
const deviceType: string | undefined = BrowserHelper.userAgentInfo.getDevice().type;
if (deviceType != null && ["mobile", "tablet"].includes(deviceType)) {
singleImageModeForced = singleImageMode.mobile.always;
singleImageModeFallbackAllowed = singleImageMode.mobile.allowFallback;
} else {
singleImageModeForced = singleImageMode.desktop.always;
singleImageModeFallbackAllowed = singleImageMode.desktop.allowFallback;
}
const browserCompatibility: BrowserCompatibility = BrowserHelper.checkBrowserCompatibility();
if (
!browserCompatibility.scannerSupport ||
(!singleImageModeForced && !singleImageModeFallbackAllowed && !browserCompatibility.fullSupport)
) {
return Promise.reject(new UnsupportedBrowserError(browserCompatibility));
}
if (userLicenseKey == null) {
return Promise.reject(
new CustomError({
name: "LibraryNotConfiguredError",
message: "The library has not correctly been configured yet, please call 'configure' with valid parameters"
})
);
}
if (!BrowserHelper.isValidHTMLElement(originElement)) {
return Promise.reject(
new CustomError({
name: "NoOriginElementError",
message: "A valid origin HTML element must be given"
})
);
}
const barcodePicker: BarcodePicker = new BarcodePicker(originElement, {
visible,
singleImageMode: browserCompatibility.fullSupport ? singleImageModeForced : true,
playSoundOnScan,
vibrateOnScan,
scanningPaused,
guiStyle,
videoFit,
laserArea,
viewfinderArea,
scanner,
scanSettings,
targetScanningFPS,
// tslint:disable-next-line:use-named-parameter
hideLogo: arguments[1] == null ? false : arguments[1].hideLogo === true // Hidden parameter
});
barcodePicker.cameraManager.setInteractionOptions(
enableCameraSwitcher,
enableTorchToggle,
enableTapToFocus,
enablePinchToZoom
);
barcodePicker.cameraManager.setSelectedCamera(camera);
barcodePicker.cameraManager.setSelectedCameraSettings(cameraSettings);
barcodePicker.cameraAccess = accessCamera;
// Show error in alert on ScanError by default when running on local IP address for easier customer debugging
barcodePicker.on("scanError", error => {
// istanbul ignore if
if (["localhost", "127.0.0.1", ""].includes(window.location.hostname)) {
alert(error);
}
});
if (accessCamera) {
return barcodePicker.cameraManager.setupCameras().then(() => {
return barcodePicker;
});
}
return Promise.resolve(barcodePicker);
}
/**
* Stop scanning and displaying video output, remove HTML elements added to the page,
* destroy the internal [[Scanner]] (by default) and destroy the barcode picker itself; ensuring complete cleanup.
*
* This method should be called after you don't plan to use the picker anymore,
* before the object is automatically cleaned up by JavaScript.
* The barcode picker must not be used in any way after this call.
*
* If the [[Scanner]] is or will be in use for other purposes, the relative option can be passed to prevent
* its destruction.
*
* @param destroyScanner Whether to destroy the internally used [[Scanner]] or not.
*/
public destroy(destroyScanner: boolean = true): void {
this.pauseScanning(true);
this.scanner.removeListener("ready", this.scannerReadyEventListener);
this.destroyed = true;
if (destroyScanner) {
this.scanner.destroy();
}
this.barcodePickerGui.destroy();
this.eventEmitter.removeAllListeners();
}
/**
* Apply a new set of scan settings to the internal scanner (replacing old settings).
*
* @param scanSettings The scan configuration object to be applied to the scanner.
* @returns The updated [[BarcodePicker]] object.
*/
public applyScanSettings(scanSettings: ScanSettings): BarcodePicker {
this.scanner.applyScanSettings(scanSettings);
return this;
}
/**
* @returns Whether the scanning is currently paused.
*/
public isScanningPaused(): boolean {
return this.scanningPaused;
}
/**
* Pause the recognition of codes in the input image.
*
* By default video from the camera is still shown, if the *pauseCamera* option is enabled the camera stream
* is paused (camera access is fully interrupted) and will be resumed when calling [[resumeScanning]] or
* [[accessCamera]], possibly requesting user permissions if needed.
*
* In "single image mode" the input for submitting a picture is disabled.
*
* @param pauseCamera Whether to also pause the camera stream.
* @returns The updated [[BarcodePicker]] object.
*/
public pauseScanning(pauseCamera: boolean = false): BarcodePicker {
this.scanningPaused = true;
if (pauseCamera) {
this.cameraManager.stopStream();
}
if (this.scanner.isReady()) {
this.barcodePickerGui.pauseScanning();
}
return this;
}
/**
* Resume the recognition of codes in the input image.
*
* If the camera stream was stopped when calling [[pauseScanning]], the camera stream is also resumed and
* user permissions are requested if needed to resume video input.
*
* In "single image mode" the input for submitting a picture is enabled.
*
* @returns The updated [[BarcodePicker]] object.
*/
public async resumeScanning(): Promise<BarcodePicker> {
this.scanningPaused = false;
if (this.scanner.isReady()) {
this.barcodePickerGui.resumeScanning();
}
if (this.cameraManager.activeCamera == null && this.cameraAccess) {
await this.cameraManager.setupCameras();
}
return this;
}
/**
* @returns The currently active camera.
*/
public getActiveCamera(): Camera | undefined {
return this.cameraManager.activeCamera;
}
/**
* Select a camera to be used for video input, if no camera is passed, the default one is selected.
*
* If camera access is enabled, the camera is enabled and accessed.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `PermissionDeniedError`
* - `NotAllowedError`
* - `NotFoundError`
* - `AbortError`
* - `NotReadableError`
* - `InternalError`
* - `NoCameraAvailableError`
*
* In "single image mode" this method has no effect.
*
* @param camera The new camera to be used, by default the automatically detected back camera is used.
* @param cameraSettings The camera options used when accessing the camera, by default HD resolution is used.
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is set
* (and accessed, if camera access is currently enabled).
*/
public async setActiveCamera(camera?: Camera, cameraSettings?: CameraSettings): Promise<BarcodePicker> {
if (camera == null || !this.cameraAccess) {
this.cameraManager.setSelectedCamera(camera);
this.cameraManager.setSelectedCameraSettings(cameraSettings);
if (this.cameraAccess) {
await this.cameraManager.setupCameras();
}
} else {
await this.cameraManager.initializeCameraWithSettings(camera, cameraSettings);
}
return this;
}
/**
* Try to apply new settings to the currently used camera for video input,
* if no settings are passed the default ones are set.
*
* If camera access is enabled, the camera is updated and accessed with the new settings.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `PermissionDeniedError`
* - `NotAllowedError`
* - `NotFoundError`
* - `AbortError`
* - `NotReadableError`
* - `InternalError`
* - `NoCameraAvailableError`
*
* In "single image mode" this method has no effect.
*
* @param cameraSettings The new camera options used when accessing the camera, by default HD resolution is used.
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is updated
* (and accessed, if camera access is currently enabled).
*/
public async applyCameraSettings(cameraSettings?: CameraSettings): Promise<BarcodePicker> {
if (!this.cameraAccess) {
this.cameraManager.setSelectedCameraSettings(cameraSettings);
} else {
await this.cameraManager.applyCameraSettings(cameraSettings);
}
return this;
}
/**
* @returns Whether the picker is in a visible state or not.
*/
public isVisible(): boolean {
return this.barcodePickerGui.isVisible();
}
/**
* Enable or disable picker visibility.
*
* Note that this does not affect camera access, frame processing or any other picker logic.
*
* @param visible Whether the picker is in a visible state or not.
* @returns The updated [[BarcodePicker]] object.
*/
public setVisible(visible: boolean): BarcodePicker {
this.barcodePickerGui.setVisible(visible);
return this;
}
/**
* @returns Whether the currently selected camera's video is mirrored along the vertical axis.
*/
public isMirrorImageEnabled(): boolean {
return this.barcodePickerGui.isMirrorImageEnabled();
}
/**
* Enable or disable camera video mirroring along the vertical axis.
* By default front cameras are automatically mirrored.
* This setting is applied per camera and the method has no effect if no camera is currently selected.
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether the camera video is mirrored along the vertical axis.
* @returns The updated [[BarcodePicker]] object.
*/
public setMirrorImageEnabled(enabled: boolean): BarcodePicker {
this.barcodePickerGui.setMirrorImageEnabled(enabled, true);
return this;
}
/**
* @returns Whether a sound should be played on barcode recognition (iOS requires user input).
* Note that the sound is played if there's at least a barcode not rejected via [[ScanResult.rejectCode]].
*/
public isPlaySoundOnScanEnabled(): boolean {
return this.playSoundOnScan;
}
/**
* Enable or disable playing a sound on barcode recognition (iOS requires user input).
*
* The sound is played if there's at least a barcode not rejected via [[ScanResult.rejectCode]].
*
* @param enabled Whether a sound should be played on barcode recognition.
* @returns The updated [[BarcodePicker]] object.
*/
public setPlaySoundOnScanEnabled(enabled: boolean): BarcodePicker {
this.playSoundOnScan = enabled;
return this;
}
/**
* @returns Whether the device should vibrate on barcode recognition (only Chrome & Firefox, requires user input).
* Note that the vibration is triggered if there's at least a barcode not rejected via [[ScanResult.rejectCode]].
*/
public isVibrateOnScanEnabled(): boolean {
return this.vibrateOnScan;
}
/**
* Enable or disable vibrating the device on barcode recognition (only Chrome & Firefox, requires user input).
*
* The vibration is triggered if there's at least a barcode not rejected via [[ScanResult.rejectCode]].
*
* @param enabled Whether the device should vibrate on barcode recognition.
* @returns The updated [[BarcodePicker]] object.
*/
public setVibrateOnScanEnabled(enabled: boolean): BarcodePicker {
this.vibrateOnScan = enabled;
return this;
}
/**
* @returns Whether a GUI button to switch between different cameras is shown (when available).
*/
public isCameraSwitcherEnabled(): boolean {
return this.cameraManager.isCameraSwitcherEnabled();
}
/**
* Show or hide a GUI button to switch between different cameras (when available).
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether to show a GUI button to switch between different cameras.
* @returns The updated [[BarcodePicker]] object.
*/
public setCameraSwitcherEnabled(enabled: boolean): BarcodePicker {
this.cameraManager.setCameraSwitcherEnabled(enabled).catch(
/* istanbul ignore next */ () => {
// Ignored
}
);
return this;
}
/**
* @returns Whether a GUI button to toggle device torch on/off is shown (when available, only Chrome).
*/
public isTorchToggleEnabled(): boolean {
return this.cameraManager.isTorchToggleEnabled();
}
/**
* Show or hide a GUI button to toggle device torch on/off (when available, only Chrome).
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether to show a GUI button to toggle device torch on/off.
* @returns The updated [[BarcodePicker]] object.
*/
public setTorchToggleEnabled(enabled: boolean): BarcodePicker {
this.cameraManager.setTorchToggleEnabled(enabled);
return this;
}
/**
* @returns Whether manual camera focus when clicking/tapping on the video is enabled (when available, only Chrome).
*/
public isTapToFocusEnabled(): boolean {
return this.cameraManager.isTapToFocusEnabled();
}
/**
* Enable or disable manual camera focus when clicking/tapping on the video (when available, only Chrome).
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether to enable manual camera focus when clicking/tapping on the video.
* @returns The updated [[BarcodePicker]] object.
*/
public setTapToFocusEnabled(enabled: boolean): BarcodePicker {
this.cameraManager.setTapToFocusEnabled(enabled);
return this;
}
/**
* @returns Whether camera zoom control via pinching gesture on the video is enabled (when available, only Chrome).
*/
public isPinchToZoomEnabled(): boolean {
return this.cameraManager.isPinchToZoomEnabled();
}
/**
* Enable or disable camera zoom control via pinching gesture on the video (when available, only Chrome).
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether to enable camera zoom control via pinching gesture on the video.
* @returns The updated [[BarcodePicker]] object.
*/
public setPinchToZoomEnabled(enabled: boolean): BarcodePicker {
this.cameraManager.setPinchToZoomEnabled(enabled);
return this;
}
/**
* Enable or disable the torch/flashlight of the device (when available, only Chrome).
* Changing active camera or camera settings will cause the torch to become disabled.
*
* A button on the [[BarcodePicker]] GUI to let the user toggle this functionality can also be set
* on creation via the *enableTorchToggle* option (enabled by default, when available).
*
* In "single image mode" this method has no effect.
*
* @param enabled Whether the torch should be enabled or disabled.
* @returns The updated [[BarcodePicker]] object.
*/
public setTorchEnabled(enabled: boolean): BarcodePicker {
this.cameraManager.setTorchEnabled(enabled);
return this;
}
/**
* Set the zoom level of the device (when available, only Chrome).
* Changing active camera or camera settings will cause the zoom to be reset.
*
* In "single image mode" this method has no effect.
*
* @param zoomPercentage The percentage of the max zoom (between 0 and 1).
* @returns The updated [[BarcodePicker]] object.
*/
public setZoom(zoomPercentage: number): BarcodePicker {
this.cameraManager.setZoom(zoomPercentage);
return this;
}
/**
* @returns Whether the barcode picker has loaded the external Scandit Engine library and is ready to scan.
*/
public isReady(): boolean {
return this.isReadyToWork;
}
/**
* Add the listener function to the listeners array for an event.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:bool-param-default
public on(eventName: EventName, listener: ListenerFn, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[ready]] event, fired when the external
* Scandit Engine library has been loaded and the barcode picker can thus start to scan barcodes.
* If the library has already been loaded the listener is called immediately.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @returns The updated [[BarcodePicker]] object.
*/
public on(eventName: "ready", listener: () => void): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[submitFrame]] event, fired when a new frame is submitted
* to the engine to be processed. As the frame is not processed yet, the [[ScanResult.barcodes]] property will
* always be empty (no results yet).
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
public on(
eventName: "submitFrame",
listener: (scanResult: ScanResult) => void,
// tslint:disable-next-line:bool-param-default
once?: boolean
): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[processFrame]] event, fired when a new frame is
* processed. This event is fired on every frame, independently from the number of recognized barcodes (can be none).
* The returned barcodes are affected by [[ScanSettings]]'s *codeDuplicateFilter* option.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
public on(
// tslint:disable-next-line:unified-signatures
eventName: "processFrame",
listener: (scanResult: ScanResult) => void,
// tslint:disable-next-line:bool-param-default
once?: boolean
): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[scan]] event, fired when new barcodes
* are recognized in the image frame. The returned barcodes are affected by [[ScanSettings]]'s *codeDuplicateFilter*
* option.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
public on(
// tslint:disable-next-line:unified-signatures
eventName: "scan",
listener: (scanResult: ScanResult) => void,
// tslint:disable-next-line:bool-param-default
once?: boolean
): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[scanError]] event, fired when an error occurs
* during scanning initialization and execution. The barcode picker will be automatically paused when this happens.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with an `ScanditEngineError` object.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:bool-param-default
public on(eventName: "scanError", listener: (error: Error) => void, once?: boolean): BarcodePicker;
public on(eventName: EventName, listener: ListenerFn, once: boolean = false): BarcodePicker {
if (eventName === "ready") {
if (this.isReadyToWork) {
listener();
} else {
this.eventEmitter.once(eventName, listener, this);
}
} else {
if (once === true) {
this.eventEmitter.once(eventName, listener, this);
} else {
this.eventEmitter.on(eventName, listener, this);
}
}
return this;
}
/**
* Remove the specified listener from the given event's listener array.
*
* @param eventName The name of the event from which to remove the listener.
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
public removeListener(eventName: EventName, listener: ListenerFn): BarcodePicker {
this.eventEmitter.removeListener(eventName, listener);
return this;
}
/**
* Remove all listeners from the given event's listener array.
*
* @param eventName The name of the event from which to remove all listeners.
* @returns The updated [[BarcodePicker]] object.
*/
public removeAllListeners(eventName: EventName): BarcodePicker {
this.eventEmitter.removeAllListeners(eventName);
return this;
}
/**
* *See the [[on]] method.*
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @param once <div class="tsd-signature-symbol">Default = false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:bool-param-default
public addListener(eventName: EventName, listener: ListenerFn, once?: boolean): BarcodePicker {
return this.on(eventName, listener, once);
}
/**
* Add the listener function to the listeners array for the [[ready]] event, fired when the external
* Scandit Engine library has been loaded and the barcode picker can thus start to scan barcodes.
* If the library has already been loaded the listener is called immediately.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @deprecated Use the [[on]] method instead.
*
* @param listener The listener function.
* @returns The updated [[BarcodePicker]] object.
*/
public onReady(listener: () => void): BarcodePicker {
console.warn(
"The onReady(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use on("ready", <listener>) instead.'
);
return this.on("ready", listener);
}
/**
* Add the listener function to the listeners array for the [[scan]] event, fired when new barcodes
* are recognized in the image frame. The returned barcodes are affected
* by the [[ScanSettings.setCodeDuplicateFilter]] option.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @deprecated Use the [[on]] method instead.
*
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
public onScan(listener: (scanResult: ScanResult) => void, once: boolean = false): BarcodePicker {
console.warn(
"The onScan(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use on("scan", <listener>) instead.'
);
return this.on("scan", listener, once);
}
/**
* Remove the specified listener from the [[scan]] event's listener array.
*
* @deprecated Use the [[removeListener]] method instead.
*
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
public removeScanListener(listener: (scanResult: ScanResult) => void): BarcodePicker {
console.warn(
"The removeScanListener(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use removeListener("scan", <listener>) instead.'
);
return this.removeListener("scan", listener);
}
/**
* Remove all listeners from the [[scan]] event's listener array.
*
* @deprecated Use the [[removeAllListeners]] method instead.
*
* @returns The updated [[BarcodePicker]] object.
*/
public removeScanListeners(): BarcodePicker {
console.warn(
"The removeScanListeners() method is deprecated and will be removed in the next" +
' major library version. Please use removeAllListeners("scan") instead.'
);
return this.removeAllListeners("scan");
}
/**
* Add the listener function to the listeners array for the [[scanError]] event, fired when an error occurs
* during scanning initialization and execution. The barcode picker will be automatically paused when this happens.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @deprecated Use the [[on]] method instead.
*
* @param listener The listener function, which will be invoked with an `ScanditEngineError` object.
* @param once Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public onScanError(listener: (error: Error) => void, once: boolean = false): BarcodePicker {
console.warn(
"The onScanError(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use on("scanError", <listener>) instead.'
);
return this.on("scanError", listener, once);
}
/**
* Remove the specified listener from the [[scanError]] event's listener array.
*
* @deprecated Use the [[removeListener]] method instead.
*
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeScanErrorListener(listener: (error: Error) => void): BarcodePicker {
console.warn(
"The removeScanErrorListener(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use removeListener("scanError", <listener>) instead.'
);
return this.removeListener("scanError", listener);
}
/**
* Remove all listeners from the [[scanError]] event's listener array.
*
* @deprecated Use the [[removeAllListeners]] method instead.
*
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeScanErrorListeners(): BarcodePicker {
console.warn(
"The removeScanErrorListeners() method is deprecated and will be removed in the next" +
' major library version. Please use removeAllListeners("scanError") instead.'
);
return this.removeAllListeners("scanError");
}
/**
* Add the listener function to the listeners array for the [[submitFrame]] event, fired when a new frame is submitted
* to the engine to be processed. As the frame is not processed yet, the [[ScanResult.barcodes]] property will
* always be empty (no results yet).
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @deprecated Use the [[on]] method instead.
*
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public onSubmitFrame(listener: (scanResult: ScanResult) => void, once: boolean = false): BarcodePicker {
console.warn(
"The onSubmitFrame(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use on("submitFrame", <listener>) instead.'
);
return this.on("submitFrame", listener, once);
}
/**
* Remove the specified listener from the [[submitFrame]] event's listener array.
*
* @deprecated Use the [[removeListener]] method instead.
*
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeSubmitFrameListener(listener: (scanResult: ScanResult) => void): BarcodePicker {
console.warn(
"The removeSubmitFrameListener(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use removeListener("submitFrame", <listener>) instead.'
);
return this.removeListener("submitFrame", listener);
}
/**
* Remove all listeners from the [[submitFrame]] event's listener array.
*
* @deprecated Use the [[removeAllListeners]] method instead.
*
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeSubmitFrameListeners(): BarcodePicker {
console.warn(
"The removeSubmitFrameListeners() method is deprecated and will be removed in the next" +
' major library version. Please use removeAllListeners("submitFrame") instead.'
);
return this.removeAllListeners("submitFrame");
}
/**
* Add the listener function to the listeners array for the [[processFrame]] event, fired when a new frame is
* processed. This event is fired on every frame, independently from the number of recognized barcodes (can be none).
* The returned barcodes are affected by the [[ScanSettings.setCodeDuplicateFilter]] option.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @deprecated Use the [[on]] method instead.
*
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public onProcessFrame(listener: (scanResult: ScanResult) => void, once: boolean = false): BarcodePicker {
console.warn(
"The onProcessFrame(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use on("processFrame", <listener>) instead.'
);
return this.on("processFrame", listener, once);
}
/**
* Remove the specified listener from the [[processFrame]] event's listener array.
*
* @deprecated Use the [[removeListener]] method instead.
*
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeProcessFrameListener(listener: (scanResult: ScanResult) => void): BarcodePicker {
console.warn(
"The removeProcessFrameListener(<listener>) method is deprecated and will be removed in the next" +
' major library version. Please use removeListener("processFrame", <listener>) instead.'
);
return this.removeListener("processFrame", listener);
}
/**
* Remove all listeners from the [[processFrame]] event's listener array.
*
* @deprecated Use the [[removeAllListeners]] method instead.
*
* @returns The updated [[BarcodePicker]] object.
*/
// tslint:disable-next-line:no-identical-functions
public removeProcessFrameListeners(): BarcodePicker {
console.warn(
"The removeProcessFrameListeners() method is deprecated and will be removed in the next" +
' major library version. Please use removeAllListeners("processFrame") instead.'
);
return this.removeAllListeners("processFrame");
}
/**
* Set the GUI style for the picker.
*
* In "single image mode" this method has no effect.
*
* When the GUI style is set to *laser* or *viewfinder*, the GUI will flash on barcode recognition.
* Note that the GUI will flash if there's at least a barcode not rejected via [[ScanResult.rejectCode]].
*
* @param guiStyle The new GUI style to be applied.
* @returns The updated [[BarcodePicker]] object.
*/
public setGuiStyle(guiStyle: BarcodePicker.GuiStyle): BarcodePicker {
this.barcodePickerGui.setGuiStyle(guiStyle);
return this;
}
/**
* Set the fit type for the video element of the picker.
*
* If the "cover" type is selected the maximum available search area for barcode detection is (continuously) adjusted
* automatically according to the visible area of the picker.
*
* In "single image mode" this method has no effect.
*
* @param objectFit The new fit type to be applied.
* @returns The updated [[BarcodePicker]] object.
*/
public setVideoFit(objectFit: BarcodePicker.ObjectFit): BarcodePicker {
this.barcodePickerGui.setVideoFit(objectFit);
return this;
}
/**
* Access the currently set or default camera, requesting user permissions if needed.
* This method is meant to be used after the picker has been initialized with disabled camera access
* (*accessCamera*=false) or after [[pauseScanning]] has been called with the pause camera stream option.
* Calling this doesn't do anything if the camera is already being accessed.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `PermissionDeniedError`
* - `NotAllowedError`
* - `NotFoundError`
* - `AbortError`
* - `NotReadableError`
* - `InternalError`
* - `NoCameraAvailableError`
*
* In "single image mode" this method has no effect.
*
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is accessed.
*/
public async accessCamera(): Promise<BarcodePicker> {
if (!this.cameraAccess || this.cameraManage