From 138e606dccf8c94c2de800076695f38654ab911e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=9D=B1=E6=BE=94?= Date: Sun, 29 May 2022 11:21:00 +0800 Subject: [PATCH] feat: add index argument, can jump to specific position. And remove goToIndex prop in ref fix #196 --- docs/props.md | 13 ++++++------- docs/props.zh-CN.md | 13 ++++++------- src/Carousel.tsx | 12 ++---------- src/hooks/useCarouselController.tsx | 30 +++++++++++++++++------------ src/types.ts | 10 +++------- 5 files changed, 35 insertions(+), 43 deletions(-) diff --git a/docs/props.md b/docs/props.md index 4452775b..bd22c90f 100644 --- a/docs/props.md +++ b/docs/props.md @@ -57,10 +57,9 @@ ## Ref -| name | types | description | -| ----------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| prev | ({ count = 1, animated = false, onFinished?: () => void }) => void | Scroll to previous item, it takes one optional argument (count), which allows you to specify how many items to cross | -| next | ({ count = 1, animated = false, onFinished?: () => void }) => void | Scroll to next item, it takes one optional argument (count), which allows you to specify how many items to cross | -| scrollTo | ({ count = 1, animated = false, onFinished?: () => void }) => void | Use count to scroll to a position where relative to the current position, scrollTo(-2) is equivalent to prev(2), scrollTo(2) is equivalent to next(2) | -| (deprecated)goToIndex | (index: number, animated?: boolean) => void | Go to index | -| getCurrentIndex | ()=>number | Get current item index | +| name | types | description | +| --------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| prev | ({ count: number, animated: boolean, onFinished?: () => void }) => void | Scroll to previous item, it takes one optional argument (count), which allows you to specify how many items to cross | +| next | ({ count: number, animated: boolean, onFinished?: () => void }) => void | Scroll to next item, it takes one optional argument (count), which allows you to specify how many items to cross | +| scrollTo | ({ index: number, count: number, animated: boolean, onFinished?: () => void }) => void | Use count to scroll to a position where relative to the current position, scrollTo({count:-2}) is equivalent to prev(2), scrollTo({count:2}) is equivalent to next(2). And also can jump to specific position, e.g. scrollTo({index:2,animated:false}) | +| getCurrentIndex | ()=>number | Get current item index | diff --git a/docs/props.zh-CN.md b/docs/props.zh-CN.md index 0c311a41..2a8e3de1 100644 --- a/docs/props.zh-CN.md +++ b/docs/props.zh-CN.md @@ -57,10 +57,9 @@ ## Ref -| name | types | description | -| ----------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | -| prev | ({ count = 1, animated = false, onFinished?: () => void }) => void | 切换至上一项,可以指定`count`决定切换的数量 | -| next | ({ count = 1, animated = false, onFinished?: () => void }) => void | 切换至下一张,可以指定`count`决定切换的数量 | -| scrollTo | ({ count = 1, animated = false, onFinished?: () => void }) => void | 切换到距离当前相对位置为`count`的位置,`scrollTo(-2)`等价于`prev(2)`,`scrollTo(2)`等价于`next(2)` | -| (弃用)goToIndex | (index: number, animated?: boolean) => void | 切换至指定下标元素 | -| getCurrentIndex | ()=>number | 获得当前轮播图下标 | +| name | types | description | +| --------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| prev | ({ count: number, animated: boolean, onFinished?: () => void }) => void | 切换至上一项,可以指定`count`决定切换的数量 | +| next | ({ count: number, animated: boolean, onFinished?: () => void }) => void | 切换至下一张,可以指定`count`决定切换的数量 | +| scrollTo | ({ index: number, count: number, animated: boolean, onFinished?: () => void }) => void | 切换到距离当前相对位置为`count`的位置,`scrollTo({count:-2})`等价于`prev(2)`,`scrollTo({count:2})`等价于`next(2)`. 同样可以跳转到指定位置 `scrollTo({index:2,animated:false})` | +| getCurrentIndex | ()=>number | 获得当前轮播图下标 | diff --git a/src/Carousel.tsx b/src/Carousel.tsx index 30015962..32e87e40 100644 --- a/src/Carousel.tsx +++ b/src/Carousel.tsx @@ -84,7 +84,7 @@ const Carousel = React.forwardRef>( duration: scrollAnimationDuration, }); - const { to, next, prev, scrollTo, getSharedIndex, getCurrentIndex } = + const { next, prev, scrollTo, getSharedIndex, getCurrentIndex } = carouselController; const { start: startAutoPlay, pause: pauseAutoPlay } = useAutoPlay({ @@ -137,23 +137,15 @@ const Carousel = React.forwardRef>( startAutoPlay, ]); - const goToIndex = React.useCallback( - (i: number, animated?: boolean) => { - to(i, animated); - }, - [to] - ); - React.useImperativeHandle( ref, () => ({ next, prev, getCurrentIndex, - goToIndex, scrollTo, }), - [getCurrentIndex, goToIndex, next, prev, scrollTo] + [getCurrentIndex, next, prev, scrollTo] ); const visibleRanges = useVisibleRanges({ diff --git a/src/hooks/useCarouselController.tsx b/src/hooks/useCarouselController.tsx index eee89e18..d5324104 100644 --- a/src/hooks/useCarouselController.tsx +++ b/src/hooks/useCarouselController.tsx @@ -33,7 +33,6 @@ export interface ICarouselController { prev: (opts?: TCarouselActionOptions) => void; next: (opts?: TCarouselActionOptions) => void; getCurrentIndex: () => number; - to: (index: number, animated?: boolean) => void; scrollTo: (opts?: TCarouselActionOptions) => void; } @@ -225,21 +224,22 @@ export function useCarouselController(options: IOpts): ICarouselController { ); const to = React.useCallback( - (idx: number, animated: boolean = false) => { - if (idx === index.value) return; + (opts: { i: number; animated: boolean; onFinished?: () => void }) => { + const { i, animated = false, onFinished } = opts; + if (i === index.value) return; if (!canSliding()) return; onScrollBegin?.(); - const offset = handlerOffsetX.value + (index.value - idx) * size; + const offset = handlerOffsetX.value + (index.value - i) * size; if (animated) { - index.value = idx; - handlerOffsetX.value = scrollWithTiming(offset); + index.value = i; + handlerOffsetX.value = scrollWithTiming(offset, onFinished); } else { handlerOffsetX.value = offset; - index.value = idx; - runOnJS(onScrollEnd)(); + index.value = i; + onFinished?.(); } }, [ @@ -249,28 +249,34 @@ export function useCarouselController(options: IOpts): ICarouselController { handlerOffsetX, size, scrollWithTiming, - onScrollEnd, ] ); const scrollTo = React.useCallback( (opts: TCarouselActionOptions = {}) => { - const { count, animated = false, onFinished } = opts; + const { index: i, count, animated = false, onFinished } = opts; + + if (i) { + to({ i, animated, onFinished }); + return; + } + if (!count) { return; } + const n = Math.round(count); + if (n < 0) { prev({ count: Math.abs(n), animated, onFinished }); } else { next({ count: n, animated, onFinished }); } }, - [prev, next] + [prev, next, to] ); return { - to, next, prev, scrollTo, diff --git a/src/types.ts b/src/types.ts index 29487ce5..1dbba864 100644 --- a/src/types.ts +++ b/src/types.ts @@ -189,21 +189,16 @@ export interface ICarouselInstance { * Scroll to previous item, it takes one optional argument (count), * which allows you to specify how many items to cross */ - prev: (opts?: TCarouselActionOptions) => void; + prev: (opts?: Omit) => void; /** * Scroll to next item, it takes one optional argument (count), * which allows you to specify how many items to cross */ - next: (opts?: TCarouselActionOptions) => void; + next: (opts?: Omit) => void; /** * Get current item index */ getCurrentIndex: () => number; - /** - * Go to index - * @deprecated use scrollTo instead - */ - goToIndex: (index: number, animated?: boolean) => void; /** * Use value to scroll to a position where relative to the current position, * scrollTo(-2) is equivalent to prev(2), scrollTo(2) is equivalent to next(2) @@ -222,6 +217,7 @@ export type CarouselRenderItem = ( ) => React.ReactElement; export interface TCarouselActionOptions { + index?: number; count?: number; animated?: boolean; onFinished?: () => void;