feat: BREAKING CHANGE: Express zoom
factor always in actual factor value (1, 2, 128, ...) instead of 0.0-1.0 scale (#306)
* Make `zoom` go on "factor" scale * Clean up `zoom` code * fix float conversion * fix zoom interpretation * Update docs for new zoom scale * fix float conversion
This commit is contained in:
@@ -204,7 +204,7 @@ dependencies {
|
||||
implementation jscFlavor
|
||||
}
|
||||
|
||||
implementation project(':camera')
|
||||
implementation project(':react-native-vision-camera')
|
||||
implementation "androidx.camera:camera-core:1.1.0-alpha05"
|
||||
}
|
||||
|
||||
|
@@ -2,5 +2,5 @@ rootProject.name = 'VisionCameraExample'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
|
||||
include ':camera'
|
||||
project(':camera').projectDir = new File(rootProject.projectDir, '../../android')
|
||||
include ':react-native-vision-camera'
|
||||
project(':react-native-vision-camera').projectDir = new File(rootProject.projectDir, '../../android')
|
||||
|
@@ -106,21 +106,15 @@ export const CameraPage: NavigationFunctionComponent = ({ componentId }) => {
|
||||
//#region Animated Zoom
|
||||
// This just maps the zoom factor to a percentage value.
|
||||
// so e.g. for [min, neutr., max] values [1, 2, 128] this would result in [0, 0.0081, 1]
|
||||
const minZoomFactor = device?.minZoom ?? 1;
|
||||
const neutralZoomFactor = device?.neutralZoom ?? 1;
|
||||
const maxZoomFactor = device?.maxZoom ?? 1;
|
||||
const maxZoomFactorClamped = Math.min(maxZoomFactor, MAX_ZOOM_FACTOR);
|
||||
|
||||
const neutralZoomOut = (neutralZoomFactor - minZoomFactor) / (maxZoomFactor - minZoomFactor);
|
||||
const neutralZoomIn = (neutralZoomOut / maxZoomFactorClamped) * maxZoomFactor;
|
||||
const maxZoomOut = maxZoomFactorClamped / maxZoomFactor;
|
||||
const minZoom = device?.minZoom ?? 1;
|
||||
const maxZoom = Math.min(device?.maxZoom ?? 1, MAX_ZOOM_FACTOR);
|
||||
|
||||
const cameraAnimatedProps = useAnimatedProps(() => {
|
||||
const z = interpolate(zoom.value, [0, neutralZoomIn, 1], [0, neutralZoomOut, maxZoomOut], Extrapolate.CLAMP);
|
||||
const z = Math.max(Math.min(zoom.value, maxZoom), minZoom);
|
||||
return {
|
||||
zoom: isNaN(z) ? 0 : z,
|
||||
zoom: z,
|
||||
};
|
||||
}, [maxZoomOut, neutralZoomOut, neutralZoomIn, zoom]);
|
||||
}, [maxZoom, minZoom, zoom]);
|
||||
//#endregion
|
||||
|
||||
//#region Callbacks
|
||||
@@ -165,10 +159,11 @@ export const CameraPage: NavigationFunctionComponent = ({ componentId }) => {
|
||||
//#endregion
|
||||
|
||||
//#region Effects
|
||||
const neutralZoom = device?.neutralZoom ?? 1;
|
||||
useEffect(() => {
|
||||
// Run everytime the neutralZoomScaled value changes. (reset zoom when device changes)
|
||||
zoom.value = neutralZoomIn;
|
||||
}, [neutralZoomIn, zoom]);
|
||||
zoom.value = neutralZoom;
|
||||
}, [neutralZoom, zoom]);
|
||||
//#endregion
|
||||
|
||||
//#region Pinch to Zoom Gesture
|
||||
@@ -182,7 +177,7 @@ export const CameraPage: NavigationFunctionComponent = ({ componentId }) => {
|
||||
// we're trying to map the scale gesture to a linear zoom here
|
||||
const startZoom = context.startZoom ?? 0;
|
||||
const scale = interpolate(event.scale, [1 - 1 / SCALE_FULL_ZOOM, 1, SCALE_FULL_ZOOM], [-1, 0, 1], Extrapolate.CLAMP);
|
||||
zoom.value = interpolate(scale, [-1, 0, 1], [0, startZoom, 1], Extrapolate.CLAMP);
|
||||
zoom.value = interpolate(scale, [-1, 0, 1], [minZoom, startZoom, maxZoom], Extrapolate.CLAMP);
|
||||
},
|
||||
});
|
||||
//#endregion
|
||||
@@ -237,6 +232,8 @@ export const CameraPage: NavigationFunctionComponent = ({ componentId }) => {
|
||||
camera={camera}
|
||||
onMediaCaptured={onMediaCaptured}
|
||||
cameraZoom={zoom}
|
||||
minZoom={minZoom}
|
||||
maxZoom={maxZoom}
|
||||
flash={supportsFlash ? flash : 'off'}
|
||||
enabled={isCameraInitialized && isActive}
|
||||
setIsPressingButton={setIsPressingButton}
|
||||
|
@@ -32,6 +32,8 @@ interface Props extends ViewProps {
|
||||
camera: React.RefObject<Camera>;
|
||||
onMediaCaptured: (media: PhotoFile | VideoFile, type: 'photo' | 'video') => void;
|
||||
|
||||
minZoom: number;
|
||||
maxZoom: number;
|
||||
cameraZoom: Reanimated.SharedValue<number>;
|
||||
|
||||
flash: 'off' | 'on';
|
||||
@@ -44,6 +46,8 @@ interface Props extends ViewProps {
|
||||
const _CaptureButton: React.FC<Props> = ({
|
||||
camera,
|
||||
onMediaCaptured,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
cameraZoom,
|
||||
flash,
|
||||
enabled,
|
||||
@@ -191,15 +195,14 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
const offsetYForFullZoom = context.startY - yForFullZoom;
|
||||
|
||||
// extrapolate [0 ... 1] zoom -> [0 ... Y_FOR_FULL_ZOOM] finger position
|
||||
context.offsetY = interpolate(Math.sqrt(cameraZoom.value), [0, 1], [0, offsetYForFullZoom], Extrapolate.CLAMP);
|
||||
context.offsetY = interpolate(cameraZoom.value, [minZoom, maxZoom], [0, offsetYForFullZoom], Extrapolate.CLAMP);
|
||||
},
|
||||
onActive: (event, context) => {
|
||||
const offset = context.offsetY ?? 0;
|
||||
const startY = context.startY ?? SCREEN_HEIGHT;
|
||||
const yForFullZoom = startY * 0.7;
|
||||
|
||||
const zoom = interpolate(event.absoluteY - offset, [yForFullZoom, startY], [1, 0], Extrapolate.CLAMP);
|
||||
cameraZoom.value = zoom ** 2;
|
||||
cameraZoom.value = interpolate(event.absoluteY - offset, [yForFullZoom, startY], [maxZoom, minZoom], Extrapolate.CLAMP);
|
||||
},
|
||||
});
|
||||
//#endregion
|
||||
|
Reference in New Issue
Block a user