我使用react-native-gesture-handler和react-native-reanimated构建了一个捏合缩放效果。用户可以在图像的任意位置捏合并以手指之间的位置为缩放原点进行缩放。这很棒。但是,我遇到了一个问题,就是允许用户在多个捏合手势中缩放。这需要记住用户先前捏合手势的偏移量和缩放比例。目前我的代码存在一个问题,当用户第二次捏合时,手势处理程序会记住第一次捏合手势的缩放比例值,但无法正确更新缩放原点。如何解决这个问题而不增加变换语句的数量?
const prevZoomScale = useSharedValue(1)
const currZoomScale = useSharedValue(1)
const zoomScale = useDerivedValue(() => { return prevZoomScale.value * currZoomScale.value }, [prevZoomScale.value, currZoomScale.value])
const tempZoomScale = useSharedValue(1)
const prevOriginOffset = useSharedValue({x: 0, y: 0})
const tempOriginOffset = useSharedValue({x: 0, y: 0})
const currOriginOffset = useSharedValue({x: 0, y: 0})
const pinchOriginOffset = useDerivedValue(() =>
{
return {
x: (prevOriginOffset.value.x + currOriginOffset.value.x),
y: (prevOriginOffset.value.y + currOriginOffset.value.y)
}
},
[prevOriginOffset.value.x, prevOriginOffset.value.y, currOriginOffset.value.x, currOriginOffset.value.y]
)
const onPinchEvent = useAnimatedGestureHandler<PinchGestureHandlerGestureEvent>({
onStart: (_) => {
prevZoomScale.value = tempZoomScale.value
currZoomScale.value = 1
prevOriginOffset.value = tempOriginOffset.value
currOriginOffset.value = {x: _.focalX - SIZE / 2, y: _.focalY - SIZE / 2}
},
onActive: (event) => {
if ((event.scale * prevZoomScale.value) > 1) {
currZoomScale.value = event.scale
}
},
onEnd: (_) => {
tempZoomScale.value = zoomScale.value
tempOriginOffset.value = pinchOriginOffset.value
},
const animatedStyle = useAnimatedStyle(
() => ({
transform: [
{
translateX: (pinchOriginOffset.value.x)
},
{
translateY: (pinchOriginOffset.value.y)
},
{
scale: zoomScale.value
},
{
translateX: - (pinchOriginOffset.value.x)
},
{
translateY: - ( pinchOriginOffset.value.y)
}
],
}),
[]
)
return (
<View style={[styles.zoomScrollContainer, { backgroundColor: color.core.black }]}>
<PinchGestureHandler
onGestureEvent={onPinchEvent}
>
<Animated.View >
<Animated.Image
source={{ uri: zoomedImageUri }}
style={[styles.imageStyle, animatedStyle]}
>
</Animated.Image>
</Animated.View>
</PinchGestureHandler>
</View>
)