React-Native的Pinch Gesture Handler缩放位置

9
我在捏合手势处理器内部放置了一个平移手势处理器,以创建多方向滚动缩放视图的效果,一切都运行良好。但是我遇到了一个问题,当用户放大时,视图并没有在他们的手指下放大,而是在其他地方放大,位置没有保持不变。以下是我的代码:
这是一个可复现的演示:Expo Demo 这是视图:
<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));
    },
});

你的演示在Android 13上无法正常工作,无法滚动和缩放。 - undefined
1个回答

0
其实我觉得使用焦点点子的想法很棒。但是我会有所不同地去做。
也许你可以创建两个共享价值观:
const focalX = useSharedValue(0);
const focalY = useSharedValue(0);


在紧要关头:
const pinchGestureHandler = useAnimatedGestureHandler({
    onActive: (event, ctx) => {
      scale.value = event.scale;

      focalX.value = event.focalX;
      focalY.value = event.focalY;
      
      // No need to adjust translations manually
      // 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));
    },
});

在动画风格中,你可以尝试:
 const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [
          { translateX: -focalX.value },
          { translateY: -focalY.value},
          { scale: scale.value },
          { translateY: focalY.value},
          { translateX: focalX.value},
          { translateX: translateX.value },
          { translateY: translateY.value },
      ],
    };
  });

基本上,在缩放之前,我只是将缩放变换与焦点位置居中对齐。
希望这样能行:)

刚刚尝试了一下,但不幸的是似乎没有起作用,缩放位置仍然严重偏离。同时已经更新了Expo演示,加入了提出的答案。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接