Skip to content

Commit 2cfacff

Browse files
committed
fix: autoplay will scroll out of bounds
1 parent 836f224 commit 2cfacff

File tree

4 files changed

+30
-17
lines changed

4 files changed

+30
-17
lines changed

src/Carousel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function Carousel<T>(
6767
onScrollEnd: () => runOnJS(_onScrollEnd)(),
6868
onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
6969
onChange: (i) => onSnapToItem && runOnJS(onSnapToItem)(i),
70+
duration: autoPlayInterval,
7071
});
7172

7273
const {

src/ScrollViewGesture.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import Animated, {
1212
useDerivedValue,
1313
useSharedValue,
1414
withDecay,
15-
withSpring,
15+
withTiming,
1616
} from 'react-native-reanimated';
17+
import { Easing } from './constants';
1718
import { CTX } from './store';
1819

1920
type GestureContext = {
@@ -40,6 +41,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
4041
enableSnap,
4142
panGestureHandlerProps,
4243
loop: infinite,
44+
autoPlayInterval,
4345
},
4446
} = React.useContext(CTX);
4547

@@ -54,10 +56,11 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
5456
const _withSpring = React.useCallback(
5557
(toValue: number, onFinished?: () => void) => {
5658
'worklet';
57-
return withSpring(
59+
return withTiming(
5860
toValue,
5961
{
60-
damping: 100,
62+
duration: autoPlayInterval,
63+
easing: Easing.easeOutQuart,
6164
},
6265
(isFinished) => {
6366
if (isFinished) {
@@ -66,7 +69,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
6669
}
6770
);
6871
},
69-
[]
72+
[autoPlayInterval]
7073
);
7174

7275
const endWithSpring = React.useCallback(

src/constants/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
import { Easing as _Easing } from 'react-native-reanimated';
2+
13
export enum DATA_LENGTH {
24
SINGLE_ITEM = 1,
35
DOUBLE_ITEM = 2,
46
}
7+
8+
export const Easing = {
9+
easeOutQuart: _Easing.bezier(0.25, 1, 0.5, 1),
10+
};

src/hooks/useCarouselController.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import React from 'react';
22
import type Animated from 'react-native-reanimated';
3-
import { runOnJS, useSharedValue, withSpring } from 'react-native-reanimated';
3+
import { Easing } from '../constants';
4+
import { runOnJS, useSharedValue, withTiming } from 'react-native-reanimated';
45

56
interface IOpts {
67
loop: boolean;
78
size: number;
89
handlerOffsetX: Animated.SharedValue<number>;
910
disable?: boolean;
11+
duration?: number;
12+
originalLength: number;
13+
length: number;
1014
onScrollBegin?: () => void;
1115
onScrollEnd?: () => void;
1216
// the length before fill data
13-
originalLength: number;
14-
length: number;
1517
onChange: (index: number) => void;
1618
}
1719

@@ -36,6 +38,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
3638
originalLength,
3739
length,
3840
onChange,
41+
duration,
3942
} = opts;
4043

4144
const index = useSharedValue<number>(0);
@@ -96,11 +99,11 @@ export function useCarouselController(opts: IOpts): ICarouselController {
9699
opts.onScrollBegin?.();
97100
}, [opts]);
98101

99-
const scrollWithSpring = React.useCallback(
102+
const scrollWithTiming = React.useCallback(
100103
(toValue: number, callback?: () => void) => {
101-
return withSpring(
104+
return withTiming(
102105
toValue,
103-
{ damping: 100 },
106+
{ duration, easing: Easing.easeOutQuart },
104107
(isFinished: boolean) => {
105108
callback?.();
106109
if (isFinished) {
@@ -109,7 +112,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
109112
}
110113
);
111114
},
112-
[onScrollEnd]
115+
[onScrollEnd, duration]
113116
);
114117

115118
const next = React.useCallback(() => {
@@ -119,7 +122,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
119122

120123
const currentPage = Math.round(handlerOffsetX.value / size);
121124

122-
handlerOffsetX.value = scrollWithSpring((currentPage - 1) * size);
125+
handlerOffsetX.value = scrollWithTiming((currentPage - 1) * size);
123126
}, [
124127
canSliding,
125128
loop,
@@ -128,7 +131,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
128131
onScrollBegin,
129132
handlerOffsetX,
130133
size,
131-
scrollWithSpring,
134+
scrollWithTiming,
132135
]);
133136

134137
const prev = React.useCallback(() => {
@@ -138,15 +141,15 @@ export function useCarouselController(opts: IOpts): ICarouselController {
138141

139142
const currentPage = Math.round(handlerOffsetX.value / size);
140143

141-
handlerOffsetX.value = scrollWithSpring((currentPage + 1) * size);
144+
handlerOffsetX.value = scrollWithTiming((currentPage + 1) * size);
142145
}, [
143146
canSliding,
144147
loop,
145148
index.value,
146149
onScrollBegin,
147150
handlerOffsetX,
148151
size,
149-
scrollWithSpring,
152+
scrollWithTiming,
150153
]);
151154

152155
const to = React.useCallback(
@@ -159,7 +162,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
159162
const offset = handlerOffsetX.value + (index.value - idx) * size;
160163

161164
if (animated) {
162-
handlerOffsetX.value = scrollWithSpring(offset, () => {
165+
handlerOffsetX.value = scrollWithTiming(offset, () => {
163166
index.value = idx;
164167
});
165168
} else {
@@ -174,7 +177,7 @@ export function useCarouselController(opts: IOpts): ICarouselController {
174177
onScrollBegin,
175178
handlerOffsetX,
176179
size,
177-
scrollWithSpring,
180+
scrollWithTiming,
178181
onScrollEnd,
179182
]
180183
);

0 commit comments

Comments
 (0)