I am using react-native-reanimated and react-native-gesture-handler to create a view that allows you to "explore" what's inside of it (even if it exceeds its width and height).
Here's my gestureHandler
that updates translationX
& translationY
variables, later used in useAnimatedStyle
to "move" the <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 });
},
});
This code "works" in the following case:
- I have a "visible area" of
width: 100, height: 100
- "box" (element that is being panned) of
width: 160, height: 160
Here's a gif (click to view in full size):

I created an example as a Expo Snack displaying my problem. If you change INITIAL_SCALE
in Transforms.js
to 0.5
or just tap the pink box (it changes its scale to NEW_SCALE
, see onPress()
), panning in boundaries no longer works.