Skip to content

Commit 25b662d

Browse files
authored
Merge pull request #50 from dohooo/1.0.7
1.0.7
2 parents 70ab9e5 + dd30b9c commit 25b662d

File tree

6 files changed

+119
-81
lines changed

6 files changed

+119
-81
lines changed

example/src/App.tsx

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Animated, {
1515
useAnimatedStyle,
1616
useSharedValue,
1717
} from 'react-native-reanimated';
18+
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
1819

1920
const window = Dimensions.get('window');
2021

@@ -26,21 +27,25 @@ const data: ImageSourcePropType[] = [
2627

2728
export default function App() {
2829
const progressValue = useSharedValue<number>(0);
29-
const r = React.useRef<ICarouselInstance | null>(null);
30+
const defaultCarouselRef = React.useRef<ICarouselInstance | null>(null);
31+
const parallaxCarouselRef = React.useRef<ICarouselInstance | null>(null);
3032

3133
return (
3234
<View
3335
style={{
3436
flex: 1,
3537
alignItems: 'center',
3638
backgroundColor: 'black',
37-
paddingTop: 100,
39+
paddingTop: 50,
3840
}}
3941
>
40-
<View style={{ height: 240 }}>
42+
<View
43+
style={{
44+
height: 240,
45+
}}
46+
>
4147
<Carousel<ImageSourcePropType>
42-
defaultIndex={1}
43-
ref={r}
48+
ref={defaultCarouselRef}
4449
width={window.width}
4550
data={data}
4651
parallaxScrollingScale={0.8}
@@ -67,13 +72,13 @@ export default function App() {
6772
<Button
6873
title="Prev"
6974
onPress={() => {
70-
r.current?.prev();
75+
defaultCarouselRef.current?.prev();
7176
}}
7277
/>
7378
<Button
7479
title="Next"
7580
onPress={() => {
76-
r.current?.next();
81+
defaultCarouselRef.current?.next();
7782
}}
7883
/>
7984
</View>
@@ -85,6 +90,7 @@ export default function App() {
8590
mode="parallax"
8691
width={window.width}
8792
data={data}
93+
ref={parallaxCarouselRef}
8894
parallaxScrollingScale={0.8}
8995
renderItem={(source) => (
9096
<View style={{ flex: 1 }}>
@@ -114,6 +120,12 @@ export default function App() {
114120
index={index}
115121
key={index}
116122
length={data.length}
123+
onPress={() => {
124+
parallaxCarouselRef.current?.goToIndex(
125+
index,
126+
true
127+
);
128+
}}
117129
/>
118130
);
119131
})}
@@ -128,8 +140,9 @@ const PaginationItem: React.FC<{
128140
index: number;
129141
length: number;
130142
animValue: Animated.SharedValue<number>;
143+
onPress?: () => void;
131144
}> = (props) => {
132-
const { animValue, index, length } = props;
145+
const { onPress, animValue, index, length } = props;
133146
const width = 20;
134147

135148
const animStyle = useAnimatedStyle(() => {
@@ -154,22 +167,32 @@ const PaginationItem: React.FC<{
154167
],
155168
};
156169
}, [animValue, index, length]);
170+
157171
return (
158-
<View
159-
style={{
160-
backgroundColor: 'white',
161-
width,
162-
height: width,
163-
borderRadius: 50,
164-
overflow: 'hidden',
165-
}}
172+
<TouchableWithoutFeedback
173+
containerStyle={{ flex: 1 }}
174+
onPress={onPress}
166175
>
167-
<Animated.View
168-
style={[
169-
{ borderRadius: 50, backgroundColor: 'tomato', flex: 1 },
170-
animStyle,
171-
]}
172-
/>
173-
</View>
176+
<View
177+
style={{
178+
backgroundColor: 'white',
179+
width,
180+
height: width,
181+
borderRadius: 50,
182+
overflow: 'hidden',
183+
}}
184+
>
185+
<Animated.View
186+
style={[
187+
{
188+
borderRadius: 50,
189+
backgroundColor: 'tomato',
190+
flex: 1,
191+
},
192+
animStyle,
193+
]}
194+
/>
195+
</View>
196+
</TouchableWithoutFeedback>
174197
);
175198
};

src/Carousel.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { CarouselItem } from './CarouselItem';
1818
import type { TMode } from './layouts';
1919
import { ParallaxLayout } from './layouts/index';
2020
import { useCarouselController } from './hooks/useCarouselController';
21-
import { useComputedAnim } from './hooks/useComputedAnim';
2221
import { useAutoPlay } from './hooks/useAutoPlay';
2322
import { useIndexController } from './hooks/useIndexController';
2423
import { usePropsErrorBoundary } from './hooks/usePropsErrorBoundary';
@@ -204,8 +203,6 @@ function Carousel<T extends unknown = any>(
204203
return _data;
205204
}, [_data, loop]);
206205

207-
const computedAnimResult = useComputedAnim(width, data.length);
208-
209206
const indexController = useIndexController({
210207
originalLength: _data.length,
211208
length: data.length,
@@ -247,13 +244,14 @@ function Carousel<T extends unknown = any>(
247244
}, [sharedPreIndex, sharedIndex, computedIndex, props, run]);
248245

249246
const offsetX = useDerivedValue(() => {
250-
const x = handlerOffsetX.value % computedAnimResult.TOTAL_WIDTH;
247+
const totalWidth = width * data.length;
248+
const x = handlerOffsetX.value % totalWidth;
251249

252250
if (!loop) {
253251
return handlerOffsetX.value;
254252
}
255253
return isNaN(x) ? 0 : x;
256-
}, [computedAnimResult, loop]);
254+
}, [loop, width, data]);
257255

258256
useAnimatedReaction(
259257
() => offsetX.value,
@@ -389,7 +387,7 @@ function Carousel<T extends unknown = any>(
389387
<ParallaxLayout
390388
parallaxScrollingOffset={parallaxScrollingOffset}
391389
parallaxScrollingScale={parallaxScrollingScale}
392-
computedAnimResult={computedAnimResult}
390+
data={data}
393391
width={width}
394392
handlerOffsetX={offsetX}
395393
index={i}
@@ -402,7 +400,7 @@ function Carousel<T extends unknown = any>(
402400
default:
403401
return (
404402
<CarouselItem
405-
computedAnimResult={computedAnimResult}
403+
data={data}
406404
width={width}
407405
height={height}
408406
handlerOffsetX={offsetX}
@@ -418,7 +416,7 @@ function Carousel<T extends unknown = any>(
418416
[
419417
loop,
420418
mode,
421-
computedAnimResult,
419+
data,
422420
height,
423421
offsetX,
424422
parallaxScrollingOffset,

src/CarouselItem.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
11
import React from 'react';
22
import { FlexStyle, View } from 'react-native';
33
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
4-
import type { IComputedAnimResult } from './hooks/useComputedAnim';
54
import { useOffsetX } from './hooks/useOffsetX';
65

76
export const CarouselItem: React.FC<{
87
loop?: boolean;
98
index: number;
109
handlerOffsetX: Animated.SharedValue<number>;
1110
width: number;
11+
data: unknown[];
1212
height?: FlexStyle['height'];
13-
computedAnimResult: IComputedAnimResult;
1413
}> = (props) => {
1514
const {
1615
handlerOffsetX,
1716
index,
1817
children,
1918
width,
2019
height = '100%',
21-
computedAnimResult,
2220
loop,
21+
data,
2322
} = props;
23+
2424
const x = useOffsetX({
2525
handlerOffsetX,
2626
index,
2727
width,
28-
computedAnimResult,
28+
data,
2929
loop,
3030
});
31+
3132
const offsetXStyle = useAnimatedStyle(() => {
3233
return {
3334
transform: [{ translateX: x.value - index * width }],

src/hooks/useComputedAnim.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/hooks/useOffsetX.ts

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,73 @@ import Animated, {
33
interpolate,
44
useDerivedValue,
55
} from 'react-native-reanimated';
6-
import type { IComputedAnimResult } from './useComputedAnim';
76

87
interface IOpts {
98
index: number;
109
width: number;
11-
computedAnimResult: IComputedAnimResult;
1210
handlerOffsetX: Animated.SharedValue<number>;
11+
data: unknown[];
12+
type?: 'positive' | 'negative';
13+
viewCount?: number;
1314
loop?: boolean;
1415
}
1516

1617
export const useOffsetX = (opts: IOpts) => {
17-
const { handlerOffsetX, index, width, computedAnimResult, loop } = opts;
18+
const {
19+
handlerOffsetX,
20+
index,
21+
width,
22+
loop,
23+
data,
24+
type = 'positive',
25+
viewCount = Math.round((data.length - 1) / 2),
26+
} = opts;
27+
const ITEM_LENGTH = data.length;
28+
const VALID_LENGTH = ITEM_LENGTH - 1;
29+
const TOTAL_WIDTH = width * ITEM_LENGTH;
30+
const HALF_WIDTH = 0.5 * width;
31+
1832
const x = useDerivedValue(() => {
19-
const { MAX, MIN, TOTAL_WIDTH, HALF_WIDTH } = computedAnimResult;
33+
const defaultPos = width * index;
2034
if (loop) {
21-
const defaultPos = width * index;
22-
const startPos =
23-
defaultPos > MAX
24-
? MAX - defaultPos
25-
: defaultPos < MIN
26-
? MIN - defaultPos
27-
: defaultPos;
35+
function getDefaultPos(
36+
_type: 'positive' | 'negative',
37+
_count: number
38+
): {
39+
MAX: number;
40+
MIN: number;
41+
startPos: number;
42+
} {
43+
let MAX = null;
44+
let MIN = null;
45+
46+
let startPos: number = defaultPos;
47+
48+
if (_type === 'positive') {
49+
MAX = _count * width;
50+
MIN = -(VALID_LENGTH - _count) * width;
51+
} else {
52+
MAX = (VALID_LENGTH - _count) * width;
53+
MIN = -_count * width;
54+
}
55+
56+
if (defaultPos > MAX) {
57+
startPos = MAX - defaultPos;
58+
}
59+
60+
return {
61+
startPos,
62+
MAX,
63+
MIN,
64+
};
65+
}
66+
67+
const { startPos, MAX, MIN } = getDefaultPos(type, viewCount);
2868

2969
const inputRange = [
3070
-TOTAL_WIDTH,
31-
-(MAX + HALF_WIDTH) - startPos - 1,
32-
-(MAX + HALF_WIDTH) - startPos,
71+
MIN - HALF_WIDTH - startPos - 1,
72+
MIN - HALF_WIDTH - startPos,
3373
0,
3474
MAX + HALF_WIDTH - startPos,
3575
MAX + HALF_WIDTH - startPos + 1,
@@ -38,11 +78,11 @@ export const useOffsetX = (opts: IOpts) => {
3878

3979
const outputRange = [
4080
startPos,
41-
1.5 * width - 1,
42-
-(MAX + HALF_WIDTH),
81+
MAX + HALF_WIDTH - 1,
82+
MIN - HALF_WIDTH,
4383
startPos,
4484
MAX + HALF_WIDTH,
45-
-(1.5 * width - 1),
85+
MIN - HALF_WIDTH + 1,
4686
startPos,
4787
];
4888

@@ -54,8 +94,8 @@ export const useOffsetX = (opts: IOpts) => {
5494
);
5595
}
5696

57-
const startPos = width * index;
58-
return handlerOffsetX.value + startPos;
59-
}, [loop, computedAnimResult]);
97+
return handlerOffsetX.value + defaultPos;
98+
}, [loop, data, viewCount, type]);
99+
60100
return x;
61101
};

0 commit comments

Comments
 (0)