Skip to content

Commit

Permalink
fix: index bug
Browse files Browse the repository at this point in the history
fix #185
  • Loading branch information
dohooo committed May 18, 2022
1 parent 9741beb commit 57a18ad
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 59 deletions.
2 changes: 1 addition & 1 deletion docs/props.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
| testID || | string | Used to locate this view in end-to-end tests |
| onSnapToItem || | (index: number) => void | Callback fired when navigating to an item |
| onScrollBegin || | () => void | Callback fired when scroll begin |
| onScrollEnd || | (previous: number, current: number) => void | Callback fired when scroll end |
| onScrollEnd || | (index: number) => void | Callback fired when scroll end |
| withAnimation || | {type: 'spring';config: WithSpringConfig;} \| {type: 'timing';config: WithTimingConfig;} | Specifies the scrolling animation effect |
| panGestureHandlerProps || {} | Omit<Partial\<PanGestureHandlerProps\>,'onHandlerStateChange'> | PanGestureHandler props |
| windowSize || 0 | number | The maximum number of items that can respond to pan gesture events, `0` means all items will respond to pan gesture events |
Expand Down
2 changes: 1 addition & 1 deletion docs/props.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
| testID || | string | 在 E2E 测试中用来定位视图 |
| onSnapToItem || | (index: number) => void | 切换至另一张轮播图时触发 |
| onScrollBegin || | () => void | 切换动画开始时触发 |
| onScrollEnd || | (previous: number, current: number) => void | 切换动画结束时触发 |
| onScrollEnd || | (index: number) => void | 切换动画结束时触发 |
| withAnimation || | {type: 'spring';config: WithSpringConfig;} \| {type: 'timing';config: WithTimingConfig;} | 指定滚动时的动画效果 |
| panGestureHandlerProps || {} | Omit<Partial\<PanGestureHandlerProps\>,'onHandlerStateChange'> | PanGestureHandler props |
| windowSize || 0 | number | 能响应平移手势事件的最大 item 数量,0 表示所有元素都会先响应 |
Expand Down
32 changes: 8 additions & 24 deletions src/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import React from 'react';
import Animated, {
runOnJS,
runOnUI,
useDerivedValue,
} from 'react-native-reanimated';
import Animated, { runOnJS, useDerivedValue } from 'react-native-reanimated';

import { useCarouselController } from './hooks/useCarouselController';
import { useAutoPlay } from './hooks/useAutoPlay';
Expand Down Expand Up @@ -88,15 +84,8 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
duration: scrollAnimationDuration,
});

const {
sharedIndex,
sharedPreIndex,
to,
next,
prev,
scrollTo,
getCurrentIndex,
} = carouselController;
const { to, next, prev, scrollTo, getSharedIndex, getCurrentIndex } =
carouselController;

const { start: startAutoPlay, pause: pauseAutoPlay } = useAutoPlay({
autoPlay,
Expand All @@ -106,17 +95,15 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
});

const _onScrollEnd = React.useCallback(() => {
'worklet';
const _sharedIndex = Math.round(sharedIndex.value);
const _sharedPreIndex = Math.round(sharedPreIndex.value);
const _sharedIndex = Math.round(getSharedIndex());

if (onSnapToItem) {
runOnJS(onSnapToItem)(_sharedIndex);
onSnapToItem(_sharedIndex);
}
if (onScrollEnd) {
runOnJS(onScrollEnd)(_sharedPreIndex, _sharedIndex);
onScrollEnd(_sharedIndex);
}
}, [onSnapToItem, onScrollEnd, sharedIndex, sharedPreIndex]);
}, [onSnapToItem, onScrollEnd, getSharedIndex]);

const scrollViewGestureOnScrollBegin = React.useCallback(() => {
pauseAutoPlay();
Expand All @@ -125,10 +112,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(

const scrollViewGestureOnScrollEnd = React.useCallback(() => {
startAutoPlay();
/**
* TODO magic
*/
runOnUI(_onScrollEnd)();
_onScrollEnd();
}, [_onScrollEnd, startAutoPlay]);

const scrollViewGestureOnTouchBegin = React.useCallback(pauseAutoPlay, [
Expand Down
78 changes: 46 additions & 32 deletions src/hooks/useCarouselController.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import React, { useRef } from 'react';
import type Animated from 'react-native-reanimated';
import { Easing } from '../constants';
import {
runOnJS,
useDerivedValue,
useAnimatedReaction,
useSharedValue,
} from 'react-native-reanimated';
import type {
Expand All @@ -13,6 +13,7 @@ import type {
} from '../types';
import { dealWithAnimation } from '@/utils/dealWithAnimation';
import { convertToSharedIndex } from '@/utils/computedWithAutoFillData';
import { round } from '@/utils/log';

interface IOpts {
loop: boolean;
Expand All @@ -28,8 +29,7 @@ interface IOpts {
}

export interface ICarouselController {
sharedIndex: Animated.SharedValue<number>;
sharedPreIndex: Animated.SharedValue<number>;
getSharedIndex: () => number;
prev: (opts?: TCarouselActionOptions) => void;
next: (opts?: TCarouselActionOptions) => void;
getCurrentIndex: () => number;
Expand Down Expand Up @@ -60,8 +60,8 @@ export function useCarouselController(options: IOpts): ICarouselController {

const index = useSharedValue<number>(defaultIndex);
// The Index displayed to the user
const sharedIndex = useSharedValue<number>(defaultIndex);
const sharedPreIndex = useSharedValue<number>(defaultIndex);
const sharedIndex = useRef<number>(defaultIndex);
const sharedPreIndex = useRef<number>(defaultIndex);

const currentFixedPage = React.useCallback(() => {
if (loop) {
Expand All @@ -76,31 +76,46 @@ export function useCarouselController(options: IOpts): ICarouselController {
);
}, [handlerOffsetX, dataInfo, size, loop]);

useDerivedValue(() => {
const handlerOffsetXValue = handlerOffsetX.value;
sharedPreIndex.value = sharedIndex.value;
const toInt = (handlerOffsetXValue / size) % dataInfo.length;
const isPositive = handlerOffsetXValue <= 0;
const i = isPositive
? Math.abs(toInt)
: Math.abs(toInt > 0 ? dataInfo.length - toInt : 0);
index.value = i;
sharedIndex.value = convertToSharedIndex({
function setSharedIndex(newSharedIndex: number) {
sharedIndex.current = newSharedIndex;
}

useAnimatedReaction(
() => {
const handlerOffsetXValue = handlerOffsetX.value;
const toInt = round(handlerOffsetXValue / size) % dataInfo.length;
const isPositive = handlerOffsetXValue <= 0;
const i = isPositive
? Math.abs(toInt)
: Math.abs(toInt > 0 ? dataInfo.length - toInt : 0);

const newSharedIndexValue = convertToSharedIndex({
loop,
rawDataLength: dataInfo.originalLength,
autoFillData: autoFillData!,
index: i,
});

return {
i,
newSharedIndexValue,
};
},
({ i, newSharedIndexValue }) => {
index.value = i;
runOnJS(setSharedIndex)(newSharedIndexValue);
},
[
sharedPreIndex,
sharedIndex,
size,
dataInfo,
index,
loop,
rawDataLength: dataInfo.originalLength,
autoFillData: autoFillData!,
index: i,
});
}, [
sharedPreIndex,
sharedIndex,
size,
dataInfo,
index,
loop,
autoFillData,
handlerOffsetX,
]);
autoFillData,
handlerOffsetX,
]
);

const getCurrentIndex = React.useCallback(() => {
return index.value;
Expand Down Expand Up @@ -255,12 +270,11 @@ export function useCarouselController(options: IOpts): ICarouselController {
);

return {
sharedIndex,
sharedPreIndex,
to,
next,
prev,
scrollTo,
getCurrentIndex,
getSharedIndex: () => sharedIndex.current,
};
}
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export type TCarouselProps<T = any> = {
/**
* On scroll end
*/
onScrollEnd?: (previous: number, current: number) => void;
onScrollEnd?: (index: number) => void;
/**
* On progress change
* @param offsetProgress Total of offset distance (0 390 780 ...)
Expand Down
5 changes: 5 additions & 0 deletions src/utils/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
export function log(...msg: any) {
console.log(...msg);
}

export function round(number: number) {
'worklet';
return Math.round(number);
}

0 comments on commit 57a18ad

Please sign in to comment.