EddyVerbruggen / nativescript-barcodescanner

🔎 NativeScript QR / barcode (bulk)scanner plugin
MIT License
293 stars 73 forks source link

Feature Request: zoom capability scanner #237

Closed bradmartin closed 4 years ago

bradmartin commented 4 years ago

We've implemented this directly accessing the camera and camerView members of the scanner for android/iOS.

Was simple enough to just modify for specific scenarios instead of making a PR without thinking out the public API to make possible.

Below is for a vue app:

iOS has a max zoom value that is accessed from a camera property

    <Slider
                    @valueChange="onValueChanged"
                    minValue="1"
                    android:maxValue="100"
                    :ios:maxValue="iOSMaxZoom"
                    padding="6"
                    width="100%"
                />
    onScannerLoaded() {
        // using a timeout to ensure the camera is loaded and opened or it'll be null
        setTimeout(() => {
            // get the native cameras
            if (isAndroid) {
                // https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/27a0ef2ec54726d31854689353f1f45eefcc2f23/src/mlkit/mlkit-cameraview.android.ts#L147
                this.camera = (this.$refs.scanner as any).nativeView.camera;
            } else {
                // https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/27a0ef2ec54726d31854689353f1f45eefcc2f23/src/mlkit/mlkit-cameraview.ios.ts#L94
                this.camera = (this.$refs.scanner as any).nativeView.captureDevice;
                this.iOSMaxZoom = this.camera.maxAvailableVideoZoomFactor;
                // to adjust the camera zoom we must lock the configuration before changing the AVCaptureDevice zoom
                // https://developer.apple.com/documentation/avfoundation/avcapturedevice/1624611-videozoomfactor
                this.camera.lockForConfiguration();
            }
        }, 1000);
    }

So this gives us the native cameras for each platform.

Then we have:

    private _setZoom(level = 0) {
        if (isAndroid) {
            try {
                const params = this.camera.getParameters();
                const zoomLevel = Math.round(
                    scale(level, 0, 100, 0, params.getMaxZoom())
                );
                params.setZoom(zoomLevel);
                this.camera.setParameters(params);
            } catch (err) {
                console.log(err);
            }
        } else {
            try {
                const zoomLevel = Math.round(scale(level, 1, 100, 1, this.iOSMaxZoom));
                this.camera.rampToVideoZoomFactorWithRate(zoomLevel, 2.0);
            } catch (err) {
                console.log(err);
            }
        }
    }

      // bound to a slider in the UI that passes the slider value into the zooming calls.
    onValueChanged(args) {
        this._setZoom(args.value);
    }

// to calculate the scaling zoom
const scale = (
    num: number,
    in_min: number,
    in_max: number,
    out_min: number,
    out_max: number
) => {
    return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min;
};

@EddyVerbruggen - if you have any thoughts on making into public API I'd be happy to help work something in to the plugin source, just didn't have time working on client project to abstract it into something well thought of.

bradmartin commented 4 years ago

WRONG REPO :)