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;
};
NOTE: iOS has two method calls that are critical: one before you make changes to zoom and one method when done. It's simplest to do the prior call before you make changes, keep it unlocked for more zoom changes, and then close the config when you're leaving the component/view/page that is showing the scanner. Not sure best approach to handle this with the plugin, maybe destroyNativeView or similar event would work.
@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.
We've implemented this directly accessing the
camera
andcamerView
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
So this gives us the native cameras for each platform.
Then we have:
NOTE: iOS has two method calls that are critical: one before you make changes to zoom and one method when done. It's simplest to do the prior call before you make changes, keep it unlocked for more zoom changes, and then close the config when you're leaving the component/view/page that is showing the scanner. Not sure best approach to handle this with the plugin, maybe
destroyNativeView
or similar event would work.@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.