在缩放后平移 Animated.View,在父视图的边界内
Panning an Animated.View, after being scaled, inside boundaries of parent View
我正在使用 react-native-reanimated and react-native-gesture-handler 创建一个视图,允许您“探索”其中的内容(即使它超出了它的宽度和高度)。
这是我的 gestureHandler
更新 translationX
& translationY
变量,后来在 useAnimatedStyle
中用于“移动” <Animated.View>
:
const gestureHandler = useAnimatedGestureHandler({
onStart: (_, ctx) => {
ctx.startX = translationX.value;
ctx.startY = translationY.value;
},
onActive: (event, ctx) => {
'worklet';
translationX.value = ctx.startX + event.translationX;
translationY.value = ctx.startY + event.translationY;
// update state to view values on the screen as they change
runOnJS(setPosition)({ x: translationX.value, y: translationY.value });
},
onEnd: () => {
'worklet';
const boundedX = clamp(
translationX.value,
(BOX_WIDTH - container?.width) * -1,
0
);
const boundedY = clamp(
translationY.value,
(BOX_HEIGHT - container?.height) * -1,
0
);
// create "bounce-y" effect when moving the box back inside the bounds
translationX.value = withTiming(boundedX);
translationY.value = withTiming(boundedY);
// update state to view values on the screen as they change
runOnJS(setPosition)({ x: boundedX, y: boundedY });
},
});
此代码在以下情况下“有效”:
- 我的“可视区域”为
width: 100, height: 100
width: 160, height: 160
的“框”(正在平移的元素)
这是一个 gif (click to view in full size):
我创建了一个示例 Expo Snack 来展示我的问题。如果您将 Transforms.js
中的 INITIAL_SCALE
更改为 0.5
或仅点击粉红色框(它将其比例更改为 NEW_SCALE
,请参阅 onPress()
),则在边界内平移 no更长的作品。
我发现了问题,它使用原点(中心)缩放框,因此在应用 scale
变换之前,我必须将其转换为“假”,将其原点设置为左上角角落.
{ translateX: -BOX_WIDTH / 2 },
{ translateY: -BOX_HEIGHT / 2 },
{ scale: scale.value }, // <- NOW I am changing the scale of the box
{ translateX: BOX_WIDTH / 2 },
{ translateY: BOX_HEIGHT / 2},
我还制作了一个函数来计算外框的“边缘”,考虑到粉色框的比例:
const getEdges = () => {
'worklet';
const pointX =
(BOX_WIDTH * scale.value - VISIBLE_AREA_WIDTH) * -1;
const pointY =
(BOX_HEIGHT * scale.value - VISIBLE_AREA_HEIGHT) * -1;
return {
x: {
min: Math.min(pointX, 0),
max: Math.max(0, pointX),
},
y: {
min: Math.min(pointY, 0),
max: Math.max(0, pointY),
},
};
};
这是包含这些修复的 working Snack。
有用信息:
我正在使用 react-native-reanimated and react-native-gesture-handler 创建一个视图,允许您“探索”其中的内容(即使它超出了它的宽度和高度)。
这是我的 gestureHandler
更新 translationX
& translationY
变量,后来在 useAnimatedStyle
中用于“移动” <Animated.View>
:
const gestureHandler = useAnimatedGestureHandler({
onStart: (_, ctx) => {
ctx.startX = translationX.value;
ctx.startY = translationY.value;
},
onActive: (event, ctx) => {
'worklet';
translationX.value = ctx.startX + event.translationX;
translationY.value = ctx.startY + event.translationY;
// update state to view values on the screen as they change
runOnJS(setPosition)({ x: translationX.value, y: translationY.value });
},
onEnd: () => {
'worklet';
const boundedX = clamp(
translationX.value,
(BOX_WIDTH - container?.width) * -1,
0
);
const boundedY = clamp(
translationY.value,
(BOX_HEIGHT - container?.height) * -1,
0
);
// create "bounce-y" effect when moving the box back inside the bounds
translationX.value = withTiming(boundedX);
translationY.value = withTiming(boundedY);
// update state to view values on the screen as they change
runOnJS(setPosition)({ x: boundedX, y: boundedY });
},
});
此代码在以下情况下“有效”:
- 我的“可视区域”为
width: 100, height: 100
width: 160, height: 160
的“框”(正在平移的元素)
这是一个 gif (click to view in full size):
我创建了一个示例 Expo Snack 来展示我的问题。如果您将 Transforms.js
中的 INITIAL_SCALE
更改为 0.5
或仅点击粉红色框(它将其比例更改为 NEW_SCALE
,请参阅 onPress()
),则在边界内平移 no更长的作品。
我发现了问题,它使用原点(中心)缩放框,因此在应用 scale
变换之前,我必须将其转换为“假”,将其原点设置为左上角角落.
{ translateX: -BOX_WIDTH / 2 },
{ translateY: -BOX_HEIGHT / 2 },
{ scale: scale.value }, // <- NOW I am changing the scale of the box
{ translateX: BOX_WIDTH / 2 },
{ translateY: BOX_HEIGHT / 2},
我还制作了一个函数来计算外框的“边缘”,考虑到粉色框的比例:
const getEdges = () => {
'worklet';
const pointX =
(BOX_WIDTH * scale.value - VISIBLE_AREA_WIDTH) * -1;
const pointY =
(BOX_HEIGHT * scale.value - VISIBLE_AREA_HEIGHT) * -1;
return {
x: {
min: Math.min(pointX, 0),
max: Math.max(0, pointX),
},
y: {
min: Math.min(pointY, 0),
max: Math.max(0, pointY),
},
};
};
这是包含这些修复的 working Snack。
有用信息: