0

我只是想通过使用 reanimated 和 redash 来缩放图像。

我跟着这个教程

但是我抓取的组件位于前一个组件之上,但位于下一个组件之下。我知道这有点复杂的解释。为此,我试图绘制一个模式来更好地解释你。

在此处输入图像描述

因此,在上面的图像中,1,2 和 3 是我保存图像的卡片。我捏缩放到第二张图像,但它保持在第一个图像之上(这是我想要的),但在这种情况下,它也保持在下一张第三张卡片的下方。

我怎样才能防止这种情况?

const SIZE = shared === true ? width - 20 : width;
const styles = StyleSheet.create({
    image: {
        ...StyleSheet.absoluteFill,
        width: undefined,
        height: undefined,
        resizeMode: "contain",
    },
});
const state = new Value(State.UNDETERMINED);
const pinchRef = useRef(PinchGestureHandler);
const origin = vec.createValue(0, 0);
const pinch = vec.createValue(0, 0);
const focal = vec.createValue(0, 0);
const scale = new Value(1);
const numberOfPointers = new Value(0);
const pinchGestureHandler = onGestureEvent({
    numberOfPointers,
    scale,
    state,
    focalX: focal.x,
    focalY: focal.y,
});
const zIndex = cond(eq(state, State.ACTIVE), 3, 0);
const adjustedFocal = vec.add(
    {
        x: -SIZE / 2,
        y: -SIZE / 2,
    },
    focal
);
useCode(
    () =>
        block([
            cond(pinchBegan(state), vec.set(origin, adjustedFocal)),
            cond(
                pinchActive(state, numberOfPointers),
                vec.set(pinch, vec.minus(vec.sub(origin, adjustedFocal)))
            ),
            cond(eq(state, State.END), [
                set(pinch.x, timing({ from: pinch.x, to: 0 })),
                set(pinch.y, timing({ from: pinch.y, to: 0 })),
                set(scale, timing({ from: scale, to: 1 })),
            ]),
        ]),
    [adjustedFocal, numberOfPointers, origin, pinch, scale, state]
);
return (
    <>
        <Animated.View style={{ width: SIZE, height: SIZE, zIndex }}>
            <PinchGestureHandler ref={pinchRef} {...pinchGestureHandler}>
                <Animated.View style={StyleSheet.absoluteFill}>
                    <Animated.Image
                        style={[
                            styles.image,
                            {
                                transform: [
                                    ...translate(pinch),
                                    ...transformOrigin(origin, { scale }),
                                ],
                            },
                        ]}
                        source={{ uri: app.HOST + photo }}
                    />
                </Animated.View>
            </PinchGestureHandler>
        </Animated.View>
    </>
);

这是组件

4

1 回答 1

2

我已经对此进行了很多工作并且遇到了相反的问题,Android 在一根手指上失败并且在失败时没有启动平底锅。您需要跟踪焦点和手指来来回调整以删除和添加手指。这里有一些代码可以帮助你......

const onPinch = useAnimatedGestureHandler<PinchGestureHandlerGestureEvent>(
    {
      onActive: (evt) => {
        /**
         * The scale is clamped to a minimum of 1 and maximum of 8 for aesthetics.
         * We use the clamped value to determine a local event scale so the focal
         * point does not become out of sync with the actual photo scaling, e.g.
         * evt.scale is 20 but scale is 8, using evt.scale for offset will put the
         * photo and calculations out of sync
         */
        scale.value = clamp(offsetScale.value * evt.scale, 1, 8);
        const localEvtScale = scale.value / offsetScale.value;

        /**
         * We calculate the adjusted focal point on the photo using the events
         * focal position on the screen, screen size, and current photo offset
         */
        adjustedFocalX.value = evt.focalX - (halfScreenWidth - offsetX.value);
        adjustedFocalY.value = evt.focalY - (halfScreenHeight + offsetY.value);

        /**
         * If the number of fingers on the screen changes, the position of the
         * focal point will change and this needs to be accounted for, e.g. if
         * two fingers are on the screen the focal is between them, but if one is
         * then removed the focal is now at the remaining fingers touch position.
         * If this happens without accounting for the change the image will jump
         * around, we keep track of the previous two finger focal to adjust for this
         * change in a reduction from two fingers to one, then if another finger
         * is added again we adjust the origin to account for the difference between
         * the original two finger touch and the new two finger touch position.
         */
        if (numberOfPinchFingers.value !== evt.numberOfPointers) {
          numberOfPinchFingers.value = evt.numberOfPointers;
          if (evt.numberOfPointers === 1) {
            focalOffsetX.value = oldFocalX.value - adjustedFocalX.value;
            focalOffsetY.value = oldFocalY.value - adjustedFocalY.value;
          } else if (numberOfPinchFingers.value > 1) {
            originX.value =
              originX.value -
              (oldFocalX.value / localEvtScale -
                adjustedFocalX.value / localEvtScale);
            originY.value =
              originY.value -
              (oldFocalY.value / localEvtScale -
                adjustedFocalY.value / localEvtScale);
          }
        }

        /**
         * If pinch handler has been activated via two fingers then the fingers
         * reduced to one we keep track of the old focal using the focal offset
         * from when the number of fingers was two. We then translate the photo
         * taking into account the offset, focal, focal offset, origin, and scale.
         */
        if (numberOfPinchFingers.value === 1) {
          oldFocalX.value = adjustedFocalX.value + focalOffsetX.value;
          oldFocalY.value = adjustedFocalY.value + focalOffsetY.value;
          translateX.value =
            offsetX.value - oldFocalX.value + localEvtScale * originX.value;
          translateY.value =
            offsetY.value + oldFocalY.value - localEvtScale * originY.value;

          /**
           * If the number of fingers in the gesture is greater than one the
           * adjusted focal point is saved as the old focal and the photo is
           * translated taking into account the offset, focal, origin, and scale.
           */
        } else if (numberOfPinchFingers.value > 1) {
          oldFocalX.value = adjustedFocalX.value;
          oldFocalY.value = adjustedFocalY.value;
          translateX.value =
            offsetX.value -
            adjustedFocalX.value +
            localEvtScale * originX.value;
          translateY.value =
            offsetY.value +
            adjustedFocalY.value -
            localEvtScale * originY.value;
        }
      },
      onFinish: () => {
        /**
         * When the pinch is finished if the scale is less than 1 return the
         * photo to center, if the photo is inside the edges of the screen
         * return the photo to line up with the edges, otherwise leave the
         * photo in its current position
         */
        translateX.value =
          scale.value < 1
            ? withTiming(0)
            : translateX.value > halfScreenWidth * (scale.value - 1)
            ? withTiming(halfScreenWidth * (scale.value - 1))
            : translateX.value < -halfScreenWidth * (scale.value - 1)
            ? withTiming(-halfScreenWidth * (scale.value - 1))
            : translateX.value;

        /**
         * When the pinch is finished if the height is less than the screen
         * height return the photo to center, if the photo is inside the
         * edges of the screen return the photo to line up with the edges,
         * otherwise leave the photo in its current position
         */
        translateY.value =
          currentImageHeight * scale.value < screenHeight
            ? withTiming(0)
            : translateY.value >
              (currentImageHeight / 2) * scale.value - screenHeight / 2
            ? withTiming(
                (currentImageHeight / 2) * scale.value - screenHeight / 2,
              )
            : translateY.value <
              (-currentImageHeight / 2) * scale.value + screenHeight / 2
            ? withTiming(
                (-currentImageHeight / 2) * scale.value + screenHeight / 2,
              )
            : translateY.value;

        /**
         * If the scale has been reduced below one, i.e. zoomed out, translate
         * the zoom back to one
         */
        offsetScale.value = scale.value < 1 ? 1 : scale.value;
        scale.value = scale.value < 1 ? withTiming(1) : scale.value;

        resetTouchValues();
      },
      onStart: (evt) => {
        if (evt.numberOfPointers > 1) { // This # pointers check is WIP for android support, not needed in current iOS version
          /**
           * Cancel any previous motion animation on translations when a touch
           * begins to interrupt the animation and take over the position handling
           */
          cancelAnimation(translateX);
          cancelAnimation(translateY);
          cancelAnimation(scale);

          /**
           * Set pinch to true to stop all pan gesture interactions
           */
          isPinch.value = true;

          /**
           * Reset isSwiping as now the pan gesture handler is no longer running
           */
          isSwiping.value = IsSwiping.UNDETERMINED;

          /**
           * Set initial values for pinch gesture interaction handler
           */
          numberOfPinchFingers.value = evt.numberOfPointers;
          offsetX.value = translateX.value;
          offsetY.value = translateY.value;
          adjustedFocalX.value = evt.focalX - (halfScreenWidth - offsetX.value);
          adjustedFocalY.value =
            evt.focalY - (halfScreenHeight + offsetY.value);
          originX.value = adjustedFocalX.value;
          originY.value = adjustedFocalY.value;
          offsetScale.value = scale.value;
        }
      },
    },
    [currentImageHeight],
  );
于 2021-06-01T10:05:09.930 回答