React-Native 捏合手势处理程序缩放位置

问题描述 投票:0回答:1

我在捏合手势处理程序内有一个平移手势处理程序,用于创建多方向滚动可缩放视图的效果,一切运行良好,但我遇到的问题是,当用户放大视图时,当用户缩放时,视图不会在手指下放大视图会缩放其他地方并且不保持相同的位置,这是我的代码:

这是视图:

<PinchGestureHandler
          simultaneousHandlers={[panRef]}
          ref={pinchRef}
          onGestureEvent={pinchGestureHandler}>
          <Animated.View style={animatedStyle}>
            <PanGestureHandler
              simultaneousHandlers={[pinchRef]}
              ref={panRef}
            onGestureEvent={panGestureHandler}></PanGestureHandler>
        </Animated.View>
        </PinchGestureHandler>

这是我的处理程序:

const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);
  const scale = useSharedValue(1);
  const panRef = useRef();
  const pinchRef = useRef();

  const panGestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startX = translateX.value;
      ctx.startY = translateY.value;
    },
    onActive: (event, ctx) => {
      translateX.value = ctx.startX + event.translationX;
      translateY.value = ctx.startY + event.translationY;
    },
    onEnd: (event, ctx) => {
      translateX.value = withDecay({
        velocity: event.velocityX,
        deceleration: 0.99,
      });
      translateY.value = withDecay({
        velocity: event.velocityY,
        deceleration: 0.99,
      });
    },
  });

  const pinchGestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startScale = scale.value;
    },
    onActive: (event, ctx) => {
      scale.value = ctx.startScale * event.scale;
    },
    onEnd: (event, ctx) => {
      scale.value = withSpring(Math.min(Math.max(scale.value, 1), 3));
    },
  });

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [
        {translateX: translateX.value},
        {translateY: translateY.value},
        {scale: scale.value},
      ],
    };
  });

尝试:

尝试调整处理程序以考虑焦点,但缩放仍然远离手指点

const pinchGestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startScale = scale.value;
      ctx.startTranslateX = translateX.value;
      ctx.startTranslateY = translateY.value;
    },
    onActive: (event, ctx) => {
      scale.value = ctx.startScale * event.scale;


      const focalX = event.focalX;
      const focalY = event.focalY;
      
      // Adjust translations
      translateX.value = ctx.startTranslateX + (1 - event.scale) * (focalX - ctx.startTranslateX);
      translateY.value = ctx.startTranslateY + (1 - event.scale) * (focalY - ctx.startTranslateY);
    },
    onEnd: (_) => {
      scale.value = withSpring(Math.min(Math.max(scale.value, 1), 3));
    },
});
javascript react-native pinchzoom react-native-gesture-handler
1个回答
0
投票

在您的代码中,缩放不会在手指下方居中,因为您没有考虑到

onActive
中的
pinchGestureHandler
处理程序中捏合手势的焦点。焦点(
event.focalX
event.focalY
)表示捏合手势中涉及的两个手指之间的中心点。要在手指下进行缩放,您需要根据焦点调整比例和位置。

这是您的

pinchGestureHandler
的修订版本:

const pinchGestureHandler = useAnimatedGestureHandler({
  onStart: (_, ctx) => {
    ctx.startScale = scale.value;
    ctx.startTranslateX = translateX.value;
    ctx.startTranslateY = translateY.value;
  },
  onActive: (event, ctx) => {
    // Calculate new scale
    const newScale = ctx.startScale * event.scale;
    
    // Get the focal point (center of the pinch)
    const focalX = event.focalX;
    const focalY = event.focalY;
    
    // Calculate adjustment needed for translation
    const deltaX = focalX - ctx.startTranslateX;
    const deltaY = focalY - ctx.startTranslateY;
    
    // Apply the scale and translation
    scale.value = newScale;
    translateX.value = ctx.startTranslateX - deltaX * (newScale - ctx.startScale) / newScale;
    translateY.value = ctx.startTranslateY - deltaY * (newScale - ctx.startScale) / newScale;
  },
  onEnd: (_) => {
    scale.value = withSpring(Math.min(Math.max(scale.value, 1), 3));
  },
});

此版本的

pinchGestureHandler
使用捏合手势的焦点来调整平移(
translateX.value
translateY.value
),以便缩放看起来发生在用户的手指下方。

记住要彻底测试,尤其是平移和捏合手势之间的交互,以确保这符合您的要求。

© www.soinside.com 2019 - 2024. All rights reserved.