Hi! 👋
Firstly, thanks for your work on this project! 🙂
I noticed that even when overscrollEnabled is set to false, the carousel could still overscroll beyond its bounds. For example:
- When swiping left on the first slide, the carousel would move slightly past the first item.
- When swiping right on the last slide, it could overshoot beyond the last item.
The problem was that the translation value was still being updated with the pan gesture even when overscrollEnabled was false. This diff it by clamping the translation strictly between the first and last items whenever overscrollEnabled is false. In other words, it prevents any overscroll by limiting the translation.value to the valid range.
Problem:
Even when overscrollEnabled = false, the carousel could still be overscrolled at the first or last slide.
Previous logic:
translation.value = panOffset.value + panTranslation;
Here:
- panTranslation is the user’s drag movement
- panOffset.value is the current carousel position
Example:
If the user is at the last slide (translation.value = -max.value)
And swipes from right to left (panTranslation < 0)
nextTranslation = panOffset.value + panTranslation
= -max + (-10)
= -max - 10
Without bounds checking, translation.value goes beyond the last slide → overscroll happens, even if overscrollEnabled is false.
Solution:
Clamp the translation mathematically:
translation.value = Math.max(-max.value, Math.min(0, nextTranslation));
- lowerBound = -max.value → last slide
- upperBound = 0 → first slide
- nextTranslation = panOffset.value + panTranslation
Now:
If nextTranslation < lowerBound → translation.value = lowerBound
If nextTranslation > upperBound → translation.value = upperBound
Values in between → normal drag works
Examples:
First slide, swiping left:
panOffset.value = 0
panTranslation = 5
nextTranslation = 5
translation.value = Math.min(0, 5) = 0
Result: Overscroll prevented
Last slide, swiping right:
panOffset.value = -max.value = -300
panTranslation = -20
nextTranslation = -320
translation.value = Math.max(-300, -320) = -300
Result: Overscroll prevented
Middle slide, normal drag:
panOffset.value = -150
panTranslation = 30
nextTranslation = -120
translation.value = Math.max(-300, Math.min(0, -120)) = -120
Result: Normal drag works
Here is the diff that solved my problem:
diff --git a/node_modules/react-native-reanimated-carousel/src/components/ScrollViewGesture.tsx b/node_modules/react-native-reanimated-carousel/src/components/ScrollViewGesture.tsx
index c935c4b..adac52b 100644
--- a/node_modules/react-native-reanimated-carousel/src/components/ScrollViewGesture.tsx
+++ b/node_modules/react-native-reanimated-carousel/src/components/ScrollViewGesture.tsx
@@ -326,18 +326,28 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
if (fixedDirection === "negative") panTranslation = -Math.abs(panTranslation);
else if (fixedDirection === "positive") panTranslation = +Math.abs(panTranslation);
+ const lowerBound = -max.value;
+ const upperBound = 0;
+ const nextTranslation = panOffset.value + panTranslation;
+
if (!loop) {
- if (translation.value > 0 || translation.value < -max.value) {
- const boundary = translation.value > 0 ? 0 : -max.value;
- const fixed = boundary - panOffset.value;
- const dynamic = panTranslation - fixed;
- translation.value = boundary + dynamic * 0.5;
+ if (!overscrollEnabled) {
+ translation.value = Math.max(lowerBound, Math.min(upperBound, nextTranslation));
+ return;
+ }
+
+ if (nextTranslation > upperBound) {
+ translation.value = upperBound + (nextTranslation - upperBound) * 0.5;
+ return;
+ }
+
+ if (nextTranslation < lowerBound) {
+ translation.value = lowerBound + (nextTranslation - lowerBound) * 0.5;
return;
}
}
- const translationValue = panOffset.value + panTranslation;
- translation.value = translationValue;
+ translation.value = nextTranslation;
},
[
isHorizontal,
Hi! 👋
Firstly, thanks for your work on this project! 🙂
I noticed that even when overscrollEnabled is set to false, the carousel could still overscroll beyond its bounds. For example:
The problem was that the translation value was still being updated with the pan gesture even when overscrollEnabled was false. This diff it by clamping the translation strictly between the first and last items whenever overscrollEnabled is false. In other words, it prevents any overscroll by limiting the translation.value to the valid range.
Problem:
Even when overscrollEnabled = false, the carousel could still be overscrolled at the first or last slide.
Previous logic:
translation.value = panOffset.value + panTranslation;Here:
Example:
If the user is at the last slide (translation.value = -max.value)
And swipes from right to left (panTranslation < 0)
Without bounds checking, translation.value goes beyond the last slide → overscroll happens, even if overscrollEnabled is false.
Solution:
Clamp the translation mathematically:
translation.value = Math.max(-max.value, Math.min(0, nextTranslation));Now:
If nextTranslation < lowerBound → translation.value = lowerBound
If nextTranslation > upperBound → translation.value = upperBound
Values in between → normal drag works
Examples:
First slide, swiping left:
Result: Overscroll prevented
Last slide, swiping right:
Result: Overscroll prevented
Middle slide, normal drag:
Result: Normal drag works
Here is the diff that solved my problem: