我正在使用 Expo 构建一个 RN 应用程序,它使用
expo-camera
的 Camera
组件。我正在尝试实现捏合缩放功能,该功能基本上是根据手势计算 0(无缩放)和 1(最大缩放)之间的数字。
MRE:https://snack.expo.dev/@fpicoral/expo-camera-zoom
// from https://stackoverflow.com/a/72524084/10893256
const onPinch = useCallback((event: GestureUpdateEvent<PinchGestureHandlerEventPayload>) => {
const velocity = event.velocity / 20;
let newZoom =
velocity > 0
? zoom + event.scale * velocity * (Platform.OS === 'ios' ? 0.01 : 25)
: zoom - event.scale * Math.abs(velocity) * (Platform.OS === 'ios' ? 0.02 : 50);
if (newZoom < 0) newZoom = 0;
else if (newZoom > 0.5) newZoom = 0.5;
setZoom(newZoom);
},
[zoom, setZoom]
);
这工作得很好,但问题是缩小了。如果你的手指从来没有离开过屏幕,一切都会很顺利。但是,如果您放大很多,抬起手指并尝试缩小,则需要多次捏合才能正确缩小。
此问题与以下事实有关:如果用户在放大后停止手势,
event.scale
将太小。我尝试跟踪累积比例,并在手势在放大和缩小之间交换时重置它,但是这也没有帮助。
编辑: 它仅在 iOS 上运行良好。在 Android 上,即使使用乘数,它也几乎根本不会放大。当我跟踪累计总和时,iOS 和 Android 都有相同的行为,但缩小的问题在两个平台上仍然存在。
我在缩小时也遇到过同样的问题。我通过根据上次缩放添加缩小系数来解决这个问题(更大的缩放=更大的系数):
const onPinch = useCallback(
(event) => {
const velocity = event.velocity / 20;
const outFactor = lastZoom * (Platform.OS === 'ios' ? 40 : 15);
let newZoom =
velocity > 0
? zoom + event.scale * velocity * (Platform.OS === 'ios' ? 0.01 : 25)
: zoom - (event.scale * (outFactor || 1)) * Math.abs(velocity) * (Platform.OS === 'ios' ? 0.02 : 50);
if (newZoom < 0) newZoom = 0;
else if (newZoom > 0.7) newZoom = 0.7;
setZoom(newZoom);
},
[zoom, setZoom, lastZoom, setLastZoom]
);
const onPinchEnd = useCallback(
(event) => {
setLastZoom(zoom);
},
[zoom, setLastZoom]
);
const pinchGesture = useMemo(
() => Gesture.Pinch().onUpdate(onPinch).onEnd(onPinchEnd),
[onPinch, onPinchEnd]
);
希望有帮助