#react-native #react-native-reanimated #redash
#react-native #react-native-реанимированный #повторная обработка
Вопрос:
Я просто пытаюсь масштабировать изображение с помощью pinch zoom, используя reanimated и redash.
Но компонент, который я захватываю, остается поверх предыдущего, но под следующим компонентом. Я знаю, что это немного сложно объяснить. Для этого я попытался нарисовать схему, чтобы лучше объяснить вам.
Итак, на изображении выше 1,2 и 3 — это мои карты, на которых хранятся изображения. И я увеличиваю масштабирование до 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>
</>
);
Вот компонент
Комментарии:
1. Вы должны вывести компонент на передний план, что означает, что анимируйте его zIndex на более высокое значение, чем другие, если вы никогда им не пользовались, просто установите для него значение 1 при выборе.
Ответ №1:
Я немного поработал с этим и столкнулся с противоположной проблемой: Android выходит из строя на 1 пальце и не запускает панорамирование при сбое. Вам нужно отслеживать фокусные точки и пальцы, чтобы переключаться между удалением и добавлением пальцев. Вот некоторый код, который поможет вам…
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],
);
Комментарии:
1. У вас где-нибудь есть полный код примера?