react-native-reanimated-carousel 2.1.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/README.zh-CN.md +10 -4
- package/lib/commonjs/Carousel.js +26 -17
- package/lib/commonjs/Carousel.js.map +1 -1
- package/lib/commonjs/ScrollViewGesture.js +34 -22
- package/lib/commonjs/ScrollViewGesture.js.map +1 -1
- package/lib/commonjs/hooks/useAutoPlay.js +27 -13
- package/lib/commonjs/hooks/useAutoPlay.js.map +1 -1
- package/lib/commonjs/hooks/useCarouselController.js +84 -24
- package/lib/commonjs/hooks/useCarouselController.js.map +1 -1
- package/lib/commonjs/hooks/useInitProps.js +13 -9
- package/lib/commonjs/hooks/useInitProps.js.map +1 -1
- package/lib/commonjs/hooks/useOnProgressChange.js +5 -5
- package/lib/commonjs/hooks/useOnProgressChange.js.map +1 -1
- package/lib/commonjs/layouts/normal.js +1 -1
- package/lib/commonjs/layouts/normal.js.map +1 -1
- package/lib/module/Carousel.js +23 -16
- package/lib/module/Carousel.js.map +1 -1
- package/lib/module/ScrollViewGesture.js +32 -22
- package/lib/module/ScrollViewGesture.js.map +1 -1
- package/lib/module/hooks/useAutoPlay.js +27 -13
- package/lib/module/hooks/useAutoPlay.js.map +1 -1
- package/lib/module/hooks/useCarouselController.js +82 -24
- package/lib/module/hooks/useCarouselController.js.map +1 -1
- package/lib/module/hooks/useInitProps.js +13 -9
- package/lib/module/hooks/useInitProps.js.map +1 -1
- package/lib/module/hooks/useOnProgressChange.js +5 -5
- package/lib/module/hooks/useOnProgressChange.js.map +1 -1
- package/lib/module/layouts/normal.js +2 -2
- package/lib/module/layouts/normal.js.map +1 -1
- package/lib/typescript/ScrollViewGesture.d.ts +3 -1
- package/lib/typescript/hooks/useAutoPlay.d.ts +1 -1
- package/lib/typescript/hooks/useCarouselController.d.ts +5 -3
- package/lib/typescript/hooks/useInitProps.d.ts +4 -5
- package/lib/typescript/hooks/useOnProgressChange.d.ts +2 -1
- package/lib/typescript/types.d.ts +22 -4
- package/package.json +5 -2
- package/src/Carousel.tsx +26 -15
- package/src/ScrollViewGesture.tsx +57 -26
- package/src/hooks/useAutoPlay.ts +25 -22
- package/src/hooks/useCarouselController.tsx +101 -42
- package/src/hooks/useInitProps.ts +30 -15
- package/src/hooks/useOnProgressChange.ts +7 -6
- package/src/layouts/normal.ts +2 -7
- package/src/types.ts +23 -4
- package/CHANGELOG.md +0 -353
- package/lib/commonjs/hooks/useIndexController.js +0 -65
- package/lib/commonjs/hooks/useIndexController.js.map +0 -1
- package/lib/module/hooks/useIndexController.js +0 -52
- package/lib/module/hooks/useIndexController.js.map +0 -1
- package/lib/typescript/hooks/useIndexController.d.ts +0 -18
- package/src/.DS_Store +0 -0
- package/src/hooks/useIndexController.ts +0 -78
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { interpolate } from 'react-native-reanimated';
|
|
2
2
|
export function normalLayout(opts) {
|
|
3
3
|
const {
|
|
4
4
|
size,
|
|
@@ -7,7 +7,7 @@ export function normalLayout(opts) {
|
|
|
7
7
|
return value => {
|
|
8
8
|
'worklet';
|
|
9
9
|
|
|
10
|
-
const translate = interpolate(value, [-1, 0, 1], [-size, 0, size]
|
|
10
|
+
const translate = interpolate(value, [-1, 0, 1], [-size, 0, size]);
|
|
11
11
|
return {
|
|
12
12
|
transform: [vertical ? {
|
|
13
13
|
translateY: translate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["normal.ts"],"names":["
|
|
1
|
+
{"version":3,"sources":["normal.ts"],"names":["interpolate","normalLayout","opts","size","vertical","value","translate","transform","translateY","translateX"],"mappings":"AAAA,SAASA,WAAT,QAA4B,yBAA5B;AAEA,OAAO,SAASC,YAAT,CAAsBC,IAAtB,EAAiE;AACpE,QAAM;AAAEC,IAAAA,IAAF;AAAQC,IAAAA;AAAR,MAAqBF,IAA3B;AAEA,SAAQG,KAAD,IAAmB;AACtB;;AACA,UAAMC,SAAS,GAAGN,WAAW,CAACK,KAAD,EAAQ,CAAC,CAAC,CAAF,EAAK,CAAL,EAAQ,CAAR,CAAR,EAAoB,CAAC,CAACF,IAAF,EAAQ,CAAR,EAAWA,IAAX,CAApB,CAA7B;AAEA,WAAO;AACHI,MAAAA,SAAS,EAAE,CACPH,QAAQ,GACF;AACII,QAAAA,UAAU,EAAEF;AADhB,OADE,GAIF;AACIG,QAAAA,UAAU,EAAEH;AADhB,OALC;AADR,KAAP;AAWH,GAfD;AAgBH","sourcesContent":["import { interpolate } from 'react-native-reanimated';\n\nexport function normalLayout(opts: { size: number; vertical: boolean }) {\n const { size, vertical } = opts;\n\n return (value: number) => {\n 'worklet';\n const translate = interpolate(value, [-1, 0, 1], [-size, 0, size]);\n\n return {\n transform: [\n vertical\n ? {\n translateY: translate,\n }\n : {\n translateX: translate,\n },\n ],\n };\n };\n}\n"]}
|
|
@@ -4,8 +4,10 @@ import Animated from 'react-native-reanimated';
|
|
|
4
4
|
interface Props {
|
|
5
5
|
size: number;
|
|
6
6
|
infinite?: boolean;
|
|
7
|
-
onScrollEnd?: () => void;
|
|
8
7
|
onScrollBegin?: () => void;
|
|
8
|
+
onScrollEnd?: () => void;
|
|
9
|
+
onTouchBegin?: () => void;
|
|
10
|
+
onTouchEnd?: () => void;
|
|
9
11
|
style?: StyleProp<ViewStyle>;
|
|
10
12
|
translation: Animated.SharedValue<number>;
|
|
11
13
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type Animated from 'react-native-reanimated';
|
|
3
|
+
import type { TCarouselActionOptions } from '../types';
|
|
3
4
|
interface IOpts {
|
|
4
5
|
loop: boolean;
|
|
5
6
|
size: number;
|
|
@@ -17,11 +18,12 @@ export interface ICarouselController {
|
|
|
17
18
|
index: Animated.SharedValue<number>;
|
|
18
19
|
sharedIndex: React.MutableRefObject<number>;
|
|
19
20
|
sharedPreIndex: React.MutableRefObject<number>;
|
|
20
|
-
prev: () => void;
|
|
21
|
-
next: () => void;
|
|
21
|
+
prev: (opts?: TCarouselActionOptions) => void;
|
|
22
|
+
next: (opts?: TCarouselActionOptions) => void;
|
|
22
23
|
computedIndex: () => void;
|
|
23
24
|
getCurrentIndex: () => number;
|
|
24
25
|
to: (index: number, animated?: boolean) => void;
|
|
26
|
+
scrollTo: (opts?: TCarouselActionOptions) => void;
|
|
25
27
|
}
|
|
26
|
-
export declare function useCarouselController(
|
|
28
|
+
export declare function useCarouselController(options: IOpts): ICarouselController;
|
|
27
29
|
export {};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { TCarouselProps } from '../types';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
width: Required<TCarouselProps>['width'];
|
|
6
|
-
height: Required<TCarouselProps>['height'];
|
|
2
|
+
declare type TGetRequiredProps<P extends keyof TCarouselProps> = Record<P, Required<TCarouselProps>[P]>;
|
|
3
|
+
export declare type TInitializeCarouselProps<T> = TCarouselProps<T> & TGetRequiredProps<'defaultIndex' | 'loop' | 'width' | 'height' | 'scrollAnimationDuration' | 'autoPlayInterval'> & {
|
|
4
|
+
rawData: T[];
|
|
7
5
|
};
|
|
8
6
|
export declare function useInitProps<T>(props: TCarouselProps<T>): TInitializeCarouselProps<T>;
|
|
7
|
+
export {};
|
|
@@ -3,4 +3,5 @@ import type { TCarouselProps } from '../types';
|
|
|
3
3
|
export declare function useOnProgressChange(opts: {
|
|
4
4
|
size: number;
|
|
5
5
|
offsetX: Animated.SharedValue<number>;
|
|
6
|
-
|
|
6
|
+
rawData: TCarouselProps['data'];
|
|
7
|
+
} & Pick<TCarouselProps, 'onProgressChange'>): void;
|
|
@@ -65,6 +65,11 @@ export declare type TCarouselProps<T = any> = {
|
|
|
65
65
|
* @description playback interval
|
|
66
66
|
*/
|
|
67
67
|
autoPlayInterval?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Time a scroll animation takes to finish
|
|
70
|
+
* @default 500 (ms)
|
|
71
|
+
*/
|
|
72
|
+
scrollAnimationDuration?: number;
|
|
68
73
|
/**
|
|
69
74
|
* Carousel container style
|
|
70
75
|
*/
|
|
@@ -125,21 +130,29 @@ export declare type TCarouselProps<T = any> = {
|
|
|
125
130
|
} & (TParallaxModeProps | TStackModeProps);
|
|
126
131
|
export interface ICarouselInstance {
|
|
127
132
|
/**
|
|
128
|
-
*
|
|
133
|
+
* Scroll to previous item, it takes one optional argument (count),
|
|
134
|
+
* which allows you to specify how many items to cross
|
|
129
135
|
*/
|
|
130
|
-
prev: () => void;
|
|
136
|
+
prev: (opts?: TCarouselActionOptions) => void;
|
|
131
137
|
/**
|
|
132
|
-
*
|
|
138
|
+
* Scroll to next item, it takes one optional argument (count),
|
|
139
|
+
* which allows you to specify how many items to cross
|
|
133
140
|
*/
|
|
134
|
-
next: () => void;
|
|
141
|
+
next: (opts?: TCarouselActionOptions) => void;
|
|
135
142
|
/**
|
|
136
143
|
* Get current item index
|
|
137
144
|
*/
|
|
138
145
|
getCurrentIndex: () => number;
|
|
139
146
|
/**
|
|
140
147
|
* Go to index
|
|
148
|
+
* @deprecated use scrollTo instead
|
|
141
149
|
*/
|
|
142
150
|
goToIndex: (index: number, animated?: boolean) => void;
|
|
151
|
+
/**
|
|
152
|
+
* Use value to scroll to a position where relative to the current position,
|
|
153
|
+
* scrollTo(-2) is equivalent to prev(2), scrollTo(2) is equivalent to next(2)
|
|
154
|
+
*/
|
|
155
|
+
scrollTo: (opts?: TCarouselActionOptions) => void;
|
|
143
156
|
}
|
|
144
157
|
export interface CarouselRenderItemInfo<ItemT> {
|
|
145
158
|
item: ItemT;
|
|
@@ -147,3 +160,8 @@ export interface CarouselRenderItemInfo<ItemT> {
|
|
|
147
160
|
animationValue: Animated.SharedValue<number>;
|
|
148
161
|
}
|
|
149
162
|
export declare type CarouselRenderItem<ItemT> = (info: CarouselRenderItemInfo<ItemT>) => React.ReactElement;
|
|
163
|
+
export interface TCarouselActionOptions {
|
|
164
|
+
count?: number;
|
|
165
|
+
animated?: boolean;
|
|
166
|
+
onFinished?: () => void;
|
|
167
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-reanimated-carousel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "Simple carousel component.fully implemented using Reanimated 2.Infinitely scrolling, very smooth.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -30,10 +30,13 @@
|
|
|
30
30
|
"release": "release-it --no-git.requireUpstream",
|
|
31
31
|
"ios": "yarn --cwd example ios",
|
|
32
32
|
"ios:pretty": "yarn --cwd example ios:pretty",
|
|
33
|
+
"web": "yarn --cwd example web",
|
|
34
|
+
"web:pretty": "yarn --cwd example web:pretty",
|
|
33
35
|
"android": "yarn --cwd example android",
|
|
34
36
|
"android:pretty": "yarn --cwd example android:pretty",
|
|
35
37
|
"pods": "cd example && pod-install --quiet",
|
|
36
|
-
"bootstrap": "yarn
|
|
38
|
+
"bootstrap": "yarn && yarn pods",
|
|
39
|
+
"deploy": "cd example && yarn deploy"
|
|
37
40
|
},
|
|
38
41
|
"keywords": [
|
|
39
42
|
"react-native",
|
package/src/Carousel.tsx
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import Animated, { runOnJS, useDerivedValue } from 'react-native-reanimated';
|
|
3
|
+
|
|
3
4
|
import { useCarouselController } from './hooks/useCarouselController';
|
|
4
5
|
import { useAutoPlay } from './hooks/useAutoPlay';
|
|
5
6
|
import { usePropsErrorBoundary } from './hooks/usePropsErrorBoundary';
|
|
6
7
|
import { ScrollViewGesture } from './ScrollViewGesture';
|
|
7
8
|
import { useVisibleRanges } from './hooks/useVisibleRanges';
|
|
9
|
+
|
|
8
10
|
import type { ICarouselInstance, TCarouselProps } from './types';
|
|
9
11
|
import { StyleSheet, View } from 'react-native';
|
|
10
12
|
import { DATA_LENGTH } from './constants';
|
|
@@ -23,6 +25,7 @@ function Carousel<T>(
|
|
|
23
25
|
|
|
24
26
|
const {
|
|
25
27
|
data,
|
|
28
|
+
rawData,
|
|
26
29
|
loop,
|
|
27
30
|
mode,
|
|
28
31
|
style,
|
|
@@ -33,6 +36,7 @@ function Carousel<T>(
|
|
|
33
36
|
windowSize,
|
|
34
37
|
autoPlayReverse,
|
|
35
38
|
autoPlayInterval,
|
|
39
|
+
scrollAnimationDuration,
|
|
36
40
|
renderItem,
|
|
37
41
|
onScrollEnd,
|
|
38
42
|
onSnapToItem,
|
|
@@ -55,7 +59,7 @@ function Carousel<T>(
|
|
|
55
59
|
}, [loop, size, data]);
|
|
56
60
|
|
|
57
61
|
usePropsErrorBoundary(props);
|
|
58
|
-
useOnProgressChange({ size, offsetX,
|
|
62
|
+
useOnProgressChange({ size, offsetX, rawData, onProgressChange });
|
|
59
63
|
|
|
60
64
|
const carouselController = useCarouselController({
|
|
61
65
|
loop,
|
|
@@ -66,8 +70,8 @@ function Carousel<T>(
|
|
|
66
70
|
originalLength: data.length,
|
|
67
71
|
onScrollEnd: () => runOnJS(_onScrollEnd)(),
|
|
68
72
|
onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
|
|
69
|
-
onChange: (i) => onSnapToItem && runOnJS(onSnapToItem)(i),
|
|
70
|
-
duration:
|
|
73
|
+
onChange: (i) => !!onSnapToItem && runOnJS(onSnapToItem)(i),
|
|
74
|
+
duration: scrollAnimationDuration,
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
const {
|
|
@@ -79,27 +83,31 @@ function Carousel<T>(
|
|
|
79
83
|
getCurrentIndex,
|
|
80
84
|
} = carouselController;
|
|
81
85
|
|
|
82
|
-
const {
|
|
86
|
+
const { start, pause } = useAutoPlay({
|
|
83
87
|
autoPlay,
|
|
84
88
|
autoPlayInterval,
|
|
85
89
|
autoPlayReverse,
|
|
86
90
|
carouselController,
|
|
87
91
|
});
|
|
88
92
|
|
|
89
|
-
const scrollViewGestureOnScrollBegin = React.useCallback(() => {
|
|
90
|
-
pause();
|
|
91
|
-
onScrollBegin?.();
|
|
92
|
-
}, [onScrollBegin, pause]);
|
|
93
|
-
|
|
94
93
|
const _onScrollEnd = React.useCallback(() => {
|
|
95
94
|
computedIndex();
|
|
96
95
|
onScrollEnd?.(sharedPreIndex.current, sharedIndex.current);
|
|
97
96
|
}, [sharedPreIndex, sharedIndex, computedIndex, onScrollEnd]);
|
|
98
97
|
|
|
98
|
+
const scrollViewGestureOnScrollBegin = React.useCallback(() => {
|
|
99
|
+
pause();
|
|
100
|
+
onScrollBegin?.();
|
|
101
|
+
}, [onScrollBegin, pause]);
|
|
102
|
+
|
|
99
103
|
const scrollViewGestureOnScrollEnd = React.useCallback(() => {
|
|
100
|
-
|
|
104
|
+
start();
|
|
101
105
|
_onScrollEnd();
|
|
102
|
-
}, [_onScrollEnd,
|
|
106
|
+
}, [_onScrollEnd, start]);
|
|
107
|
+
|
|
108
|
+
const scrollViewGestureOnTouchBegin = React.useCallback(pause, [pause]);
|
|
109
|
+
|
|
110
|
+
const scrollViewGestureOnTouchEnd = React.useCallback(start, [start]);
|
|
103
111
|
|
|
104
112
|
const goToIndex = React.useCallback(
|
|
105
113
|
(i: number, animated?: boolean) => {
|
|
@@ -115,8 +123,9 @@ function Carousel<T>(
|
|
|
115
123
|
prev,
|
|
116
124
|
getCurrentIndex,
|
|
117
125
|
goToIndex,
|
|
126
|
+
scrollTo: carouselController.scrollTo,
|
|
118
127
|
}),
|
|
119
|
-
[getCurrentIndex, goToIndex, next, prev]
|
|
128
|
+
[getCurrentIndex, goToIndex, next, prev, carouselController.scrollTo]
|
|
120
129
|
);
|
|
121
130
|
|
|
122
131
|
const visibleRanges = useVisibleRanges({
|
|
@@ -131,11 +140,11 @@ function Carousel<T>(
|
|
|
131
140
|
const renderLayout = React.useCallback(
|
|
132
141
|
(item: T, i: number) => {
|
|
133
142
|
let realIndex = i;
|
|
134
|
-
if (
|
|
143
|
+
if (rawData.length === DATA_LENGTH.SINGLE_ITEM) {
|
|
135
144
|
realIndex = i % 1;
|
|
136
145
|
}
|
|
137
146
|
|
|
138
|
-
if (
|
|
147
|
+
if (rawData.length === DATA_LENGTH.DOUBLE_ITEM) {
|
|
139
148
|
realIndex = i % 2;
|
|
140
149
|
}
|
|
141
150
|
|
|
@@ -158,7 +167,7 @@ function Carousel<T>(
|
|
|
158
167
|
);
|
|
159
168
|
},
|
|
160
169
|
[
|
|
161
|
-
|
|
170
|
+
rawData,
|
|
162
171
|
offsetX,
|
|
163
172
|
visibleRanges,
|
|
164
173
|
renderItem,
|
|
@@ -181,6 +190,8 @@ function Carousel<T>(
|
|
|
181
190
|
translation={handlerOffsetX}
|
|
182
191
|
onScrollBegin={scrollViewGestureOnScrollBegin}
|
|
183
192
|
onScrollEnd={scrollViewGestureOnScrollEnd}
|
|
193
|
+
onTouchBegin={scrollViewGestureOnTouchBegin}
|
|
194
|
+
onTouchEnd={scrollViewGestureOnTouchEnd}
|
|
184
195
|
>
|
|
185
196
|
<Animated.View
|
|
186
197
|
key={mode}
|
|
@@ -25,8 +25,10 @@ type GestureContext = {
|
|
|
25
25
|
interface Props {
|
|
26
26
|
size: number;
|
|
27
27
|
infinite?: boolean;
|
|
28
|
-
onScrollEnd?: () => void;
|
|
29
28
|
onScrollBegin?: () => void;
|
|
29
|
+
onScrollEnd?: () => void;
|
|
30
|
+
onTouchBegin?: () => void;
|
|
31
|
+
onTouchEnd?: () => void;
|
|
30
32
|
style?: StyleProp<ViewStyle>;
|
|
31
33
|
translation: Animated.SharedValue<number>;
|
|
32
34
|
}
|
|
@@ -41,11 +43,18 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
41
43
|
enableSnap,
|
|
42
44
|
panGestureHandlerProps,
|
|
43
45
|
loop: infinite,
|
|
44
|
-
|
|
46
|
+
scrollAnimationDuration,
|
|
45
47
|
},
|
|
46
48
|
} = React.useContext(CTX);
|
|
47
49
|
|
|
48
|
-
const {
|
|
50
|
+
const {
|
|
51
|
+
translation,
|
|
52
|
+
size,
|
|
53
|
+
onScrollBegin,
|
|
54
|
+
onScrollEnd,
|
|
55
|
+
onTouchBegin,
|
|
56
|
+
onTouchEnd,
|
|
57
|
+
} = props;
|
|
49
58
|
|
|
50
59
|
const maxPage = data.length;
|
|
51
60
|
const isHorizontal = useDerivedValue(() => !vertical, [vertical]);
|
|
@@ -59,7 +68,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
59
68
|
return withTiming(
|
|
60
69
|
toValue,
|
|
61
70
|
{
|
|
62
|
-
duration:
|
|
71
|
+
duration: scrollAnimationDuration,
|
|
63
72
|
easing: Easing.easeOutQuart,
|
|
64
73
|
},
|
|
65
74
|
(isFinished) => {
|
|
@@ -69,7 +78,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
69
78
|
}
|
|
70
79
|
);
|
|
71
80
|
},
|
|
72
|
-
[
|
|
81
|
+
[scrollAnimationDuration]
|
|
73
82
|
);
|
|
74
83
|
|
|
75
84
|
const endWithSpring = React.useCallback(
|
|
@@ -116,22 +125,28 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
116
125
|
]
|
|
117
126
|
);
|
|
118
127
|
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
const onFinish = React.useCallback(
|
|
129
|
+
(isFinished: boolean) => {
|
|
130
|
+
'worklet';
|
|
122
131
|
if (isFinished) {
|
|
123
132
|
touching.value = false;
|
|
124
133
|
onScrollEnd && runOnJS(onScrollEnd)();
|
|
125
134
|
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
translation.value = withDecay(
|
|
130
|
-
{ velocity: scrollEndVelocity.value },
|
|
131
|
-
onFinish
|
|
132
|
-
);
|
|
133
|
-
};
|
|
135
|
+
},
|
|
136
|
+
[onScrollEnd, touching]
|
|
137
|
+
);
|
|
134
138
|
|
|
139
|
+
const activeDecay = React.useCallback(() => {
|
|
140
|
+
'worklet';
|
|
141
|
+
touching.value = true;
|
|
142
|
+
translation.value = withDecay(
|
|
143
|
+
{ velocity: scrollEndVelocity.value },
|
|
144
|
+
onFinish
|
|
145
|
+
);
|
|
146
|
+
}, [onFinish, scrollEndVelocity.value, touching, translation]);
|
|
147
|
+
|
|
148
|
+
const resetBoundary = React.useCallback(() => {
|
|
149
|
+
'worklet';
|
|
135
150
|
if (touching.value) {
|
|
136
151
|
return;
|
|
137
152
|
}
|
|
@@ -158,15 +173,14 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
158
173
|
}
|
|
159
174
|
}
|
|
160
175
|
}, [
|
|
161
|
-
|
|
162
|
-
touching,
|
|
163
|
-
_withSpring,
|
|
176
|
+
touching.value,
|
|
164
177
|
translation,
|
|
165
|
-
scrollEndTranslation,
|
|
166
|
-
scrollEndVelocity,
|
|
167
|
-
onScrollEnd,
|
|
168
178
|
maxPage,
|
|
169
179
|
size,
|
|
180
|
+
scrollEndTranslation.value,
|
|
181
|
+
infinite,
|
|
182
|
+
activeDecay,
|
|
183
|
+
_withSpring,
|
|
170
184
|
]);
|
|
171
185
|
|
|
172
186
|
useAnimatedReaction(
|
|
@@ -176,7 +190,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
176
190
|
resetBoundary();
|
|
177
191
|
}
|
|
178
192
|
},
|
|
179
|
-
[pagingEnabled]
|
|
193
|
+
[pagingEnabled, resetBoundary]
|
|
180
194
|
);
|
|
181
195
|
|
|
182
196
|
const panGestureEventHandler = useAnimatedGestureHandler<
|
|
@@ -202,7 +216,11 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
202
216
|
!infinite &&
|
|
203
217
|
(translation.value > 0 || translation.value < -ctx.max)
|
|
204
218
|
) {
|
|
205
|
-
|
|
219
|
+
const boundary = translation.value > 0 ? 0 : -ctx.max;
|
|
220
|
+
const fixed = boundary - ctx.panOffset;
|
|
221
|
+
const dynamic = panTranslation - fixed;
|
|
222
|
+
translation.value = boundary + dynamic * 0.5;
|
|
223
|
+
return;
|
|
206
224
|
}
|
|
207
225
|
|
|
208
226
|
translation.value = ctx.panOffset + panTranslation;
|
|
@@ -223,7 +241,16 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
223
241
|
}
|
|
224
242
|
},
|
|
225
243
|
},
|
|
226
|
-
[
|
|
244
|
+
[
|
|
245
|
+
pagingEnabled,
|
|
246
|
+
isHorizontal.value,
|
|
247
|
+
infinite,
|
|
248
|
+
maxPage,
|
|
249
|
+
size,
|
|
250
|
+
enableSnap,
|
|
251
|
+
onScrollBegin,
|
|
252
|
+
onScrollEnd,
|
|
253
|
+
]
|
|
227
254
|
);
|
|
228
255
|
|
|
229
256
|
const directionStyle = React.useMemo(() => {
|
|
@@ -231,7 +258,11 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
|
|
|
231
258
|
}, [vertical]);
|
|
232
259
|
|
|
233
260
|
return (
|
|
234
|
-
<Animated.View
|
|
261
|
+
<Animated.View
|
|
262
|
+
style={[styles.container, directionStyle, style]}
|
|
263
|
+
onTouchStart={onTouchBegin}
|
|
264
|
+
onTouchEnd={onTouchEnd}
|
|
265
|
+
>
|
|
235
266
|
<PanGestureHandler
|
|
236
267
|
{...panGestureHandlerProps}
|
|
237
268
|
onGestureEvent={panGestureEventHandler}
|
package/src/hooks/useAutoPlay.ts
CHANGED
|
@@ -15,44 +15,47 @@ export function useAutoPlay(opts: {
|
|
|
15
15
|
} = opts;
|
|
16
16
|
|
|
17
17
|
const timer = React.useRef<NodeJS.Timer>();
|
|
18
|
+
const stopped = React.useRef<boolean>(!autoPlay);
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const run = React.useCallback(() => {
|
|
24
|
-
if (timer.current) {
|
|
25
|
-
pause();
|
|
20
|
+
const play = React.useCallback(() => {
|
|
21
|
+
if (stopped.current) {
|
|
22
|
+
return;
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
timer.current = setTimeout(() => {
|
|
26
|
+
autoPlayReverse
|
|
27
|
+
? carouselController.prev({ onFinished: play })
|
|
28
|
+
: carouselController.next({ onFinished: play });
|
|
29
|
+
}, autoPlayInterval);
|
|
30
|
+
}, [autoPlayReverse, autoPlayInterval, carouselController]);
|
|
31
|
+
|
|
32
|
+
const pause = React.useCallback(() => {
|
|
28
33
|
if (!autoPlay) {
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
36
|
+
timer.current && clearInterval(timer.current);
|
|
37
|
+
stopped.current = true;
|
|
38
|
+
}, [autoPlay]);
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
autoPlay,
|
|
40
|
-
autoPlayReverse,
|
|
41
|
-
autoPlayInterval,
|
|
42
|
-
carouselController,
|
|
43
|
-
]);
|
|
40
|
+
const start = React.useCallback(() => {
|
|
41
|
+
if (!autoPlay) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
stopped.current = false;
|
|
45
|
+
play();
|
|
46
|
+
}, [play, autoPlay]);
|
|
44
47
|
|
|
45
48
|
React.useEffect(() => {
|
|
46
49
|
if (autoPlay) {
|
|
47
|
-
|
|
50
|
+
start();
|
|
48
51
|
} else {
|
|
49
52
|
pause();
|
|
50
53
|
}
|
|
51
54
|
return pause;
|
|
52
|
-
}, [
|
|
55
|
+
}, [pause, start, autoPlay]);
|
|
53
56
|
|
|
54
57
|
return {
|
|
55
|
-
run,
|
|
56
58
|
pause,
|
|
59
|
+
start,
|
|
57
60
|
};
|
|
58
61
|
}
|