Skip to content

Commit

Permalink
feat: support to modify scroll animation. Add withAnimation props
Browse files Browse the repository at this point in the history
close #105
  • Loading branch information
dohooo committed Feb 1, 2022
1 parent 6bbe392 commit e3f34a4
Show file tree
Hide file tree
Showing 16 changed files with 326 additions and 75 deletions.
71 changes: 36 additions & 35 deletions docs/props.md

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions docs/props.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
| onSnapToItem || | (index: number) => void | 切换至另一张轮播图时触发 |
| onScrollBegin || | () => void | 切换动画开始时触发 |
| onScrollEnd || | (previous: number, current: number) => void | 切换动画结束时触发 |
| withAnimation || | (previous: number, current: number) => void | 指定滚动时的动画效果 |
| panGestureHandlerProps || {} | Omit<Partial\<PanGestureHandlerProps\>,'onHandlerStateChange'> | PanGestureHandler props |
| windowSize || 0 | number | 能响应平移手势事件的最大 item 数量,0 表示所有元素都会先响应 |
| onProgressChange || | onProgressChange?: (offsetProgress: number,absoluteProgress: number) => void | 当滚动进度发生变化时触发 `offsetProgress`:总的偏移值 (0 390 780 ...); `absoluteProgress`:转化为 index 的进度变化 (0 1 2 ...) |
Expand Down Expand Up @@ -52,10 +53,10 @@

## 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 = 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 | 获得当前轮播图下标 |
6 changes: 3 additions & 3 deletions example/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const path = require('path');
const pak = require('../package.json');

module.exports = function (api) {
Expand All @@ -10,10 +9,11 @@ module.exports = function (api) {
[
'module-resolver',
{
root: ['./src', '../src'],
extensions: ['.tsx', '.ts', '.js', '.json'],
alias: {
// For development, we want to alias the library to the source
[pak.name]: path.join(__dirname, '..', pak.source),
[pak.name]: '../src',
'@/utils': '../src/utils',
},
},
],
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@expo/webpack-config": "^0.16.15",
"@types/react-native-snap-carousel": "^3.8.5",
"babel-plugin-inline-dotenv": "^1.6.0",
"babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-module-resolver": "^4.1.0",
"babel-plugin-react-native-web": "^0.17.5",
"babel-preset-expo": "8.3.0",
"expo-cli": "^4.0.13",
Expand Down
3 changes: 3 additions & 0 deletions example/src/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const CustomAnimations: Array<Record<'name', keyof RootStackParamList>> = [
{
name: 'AnimTabBar',
},
{
name: 'Marquee',
},
];

const OtherPage: Array<Record<'name', keyof RootStackParamList>> = [
Expand Down
6 changes: 6 additions & 0 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ScaleFadeInOutComponent from './scale-fade-in-out';
import RotateInOutComponent from './rotate-in-out';
import RotateScaleFadeInOutComponent from './rotate-scale-fade-in-out';
import AnimTabBarComponent from './anim-tab-bar';
import MarqueeComponent from './marquee';
import { isWeb } from './utils';
import { window } from './constants';
import { QRCode } from './components/QRCode';
Expand Down Expand Up @@ -45,6 +46,7 @@ export type RootStackParamList = {
RotateInOut: undefined;
RotateScaleFadeInOut: undefined;
AnimTabBar: undefined;
Marquee: undefined;

SnapCarouselComplex: undefined;
SnapCarouselLoop: undefined;
Expand Down Expand Up @@ -139,6 +141,10 @@ function App() {
name="AnimTabBar"
component={AnimTabBarComponent}
/>
<Stack.Screen
name="Marquee"
component={MarqueeComponent}
/>

<Stack.Screen
name="SnapCarouselComplex"
Expand Down
117 changes: 117 additions & 0 deletions example/src/marquee/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import * as React from 'react';
import { View, Text } from 'react-native-ui-lib';
import Carousel from 'react-native-reanimated-carousel';
import SButton from '../components/SButton';
import { ElementsText, window } from '../constants';
import Animated, { Easing } from 'react-native-reanimated';

const PAGE_WIDTH = window.width / 2;

function ReactionContainer(props: {
text: string;
children: (
text: React.ReactElement,
layout?: { width: number }
) => React.ReactElement;
}) {
const [width, setWidth] = React.useState<number>();
const [layout, setLayout] = React.useState<{ width: number }>();

React.useEffect(() => {
if (typeof width === 'number') {
setLayout({ width });
}
}, [width]);

React.useEffect(() => {
setLayout(undefined);
}, [props.text]);

const text = (
<Animated.View
style={[
{
flexWrap: 'wrap',
width: layout?.width,
},
]}
>
<Text
onLayout={({ nativeEvent }) => {
if (typeof layout === 'undefined') {
setWidth(nativeEvent.layout.width);
}
}}
>
{props.text}
</Text>
</Animated.View>
);

return React.cloneElement(props.children(text, layout), {
key: props.text,
});
}

function Index() {
const [isVertical, setIsVertical] = React.useState(false);
const [isFast, setIsFast] = React.useState(false);
const [isAutoPlay, setIsAutoPlay] = React.useState(false);

return (
<ReactionContainer text="一二三四五六七八九十">
{(text, layout) => {
return (
<View style={{ flex: 1 }}>
<Carousel
width={layout?.width ?? PAGE_WIDTH}
height={30}
style={{
borderWidth: 1,
borderColor: 'red',
width: 200,
}}
enableSnap={false}
pagingEnabled={false}
loop
autoPlay
withAnimation={{
type: 'timing',
config: {
duration: 10000,
easing: Easing.linear,
},
}}
autoPlayInterval={0}
data={[...new Array(6).keys()]}
renderItem={() => text}
/>
<SButton
onPress={() => {
setIsVertical(!isVertical);
}}
>
{isVertical ? 'Set horizontal' : 'Set Vertical'}
</SButton>
<SButton
onPress={() => {
setIsFast(!isFast);
}}
>
{isFast ? 'NORMAL' : 'FAST'}
</SButton>
<SButton
onPress={() => {
setIsAutoPlay(!isAutoPlay);
}}
>
{ElementsText.AUTOPLAY}:{`${isAutoPlay}`}
</SButton>
</View>
);
}}
</ReactionContainer>
);
}

export default Index;
10 changes: 5 additions & 5 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3412,10 +3412,10 @@ babel-plugin-module-resolver@^3.2.0:
reselect "^3.0.1"
resolve "^1.4.0"

babel-plugin-module-resolver@^4.0.0:
babel-plugin-module-resolver@^4.1.0:
version "4.1.0"
resolved "https://registry.npm.taobao.org/babel-plugin-module-resolver/download/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2"
integrity sha1-IqTzL3RBcn7B+/SWe4Y+Hj6fM+I=
resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2"
integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==
dependencies:
find-babel-config "^1.2.0"
glob "^7.1.6"
Expand Down Expand Up @@ -11052,8 +11052,8 @@ react-native-gesture-handler@~1.10.2:

react-native-reanimated@2.2.3:
version "2.2.3"
resolved "https://registry.npmmirror.com/react-native-reanimated/download/react-native-reanimated-2.2.3.tgz#edecfe477ad9efac6f006f7e1194e8c9aa4fc6d5"
integrity sha1-7ez+R3rZ76xvAG9+EZToyapPxtU=
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.2.3.tgz#edecfe477ad9efac6f006f7e1194e8c9aa4fc6d5"
integrity sha512-d+BV39Jp4Om0ZkgVjop672/004ytlTfDT01EloO3HFZs9wR2QTuCjekq8yi3xl0G2xGZKd4DXhvqabIa7OnMYA==
dependencies:
"@babel/plugin-transform-object-assign" "^7.10.4"
fbjs "^3.0.0"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@types/jest": "^26.0.0",
"@types/react": "^16.9.19",
"@types/react-native": "0.62.13",
"babel-plugin-module-resolver": "^4.1.0",
"commitlint": "^11.0.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^7.2.0",
Expand Down
2 changes: 2 additions & 0 deletions src/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
autoPlayReverse,
autoPlayInterval,
scrollAnimationDuration,
withAnimation,
renderItem,
onScrollEnd,
onSnapToItem,
Expand Down Expand Up @@ -65,6 +66,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
handlerOffsetX,
length: data.length,
disable: !data.length,
withAnimation,
originalLength: data.length,
onScrollEnd: () => runOnJS(_onScrollEnd)(),
onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
Expand Down
32 changes: 21 additions & 11 deletions src/ScrollViewGesture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import Animated, {
useDerivedValue,
useSharedValue,
withDecay,
withTiming,
} from 'react-native-reanimated';
import { Easing } from './constants';
import { CTX } from './store';
import type { WithAnimation } from './types';
import { dealWithAnimation } from './utils/dealWithAnimation';

type GestureContext = {
panOffset: number;
Expand Down Expand Up @@ -44,6 +45,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
panGestureHandlerProps,
loop: infinite,
scrollAnimationDuration,
withAnimation,
},
} = React.useContext(CTX);

Expand All @@ -65,20 +67,27 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
const _withSpring = React.useCallback(
(toValue: number, onFinished?: () => void) => {
'worklet';
return withTiming(
toValue,
{
const callback = (isFinished: boolean) => {
'worklet';
if (isFinished) {
onFinished && runOnJS(onFinished)();
}
};

const defaultWithAnimation: WithAnimation = {
type: 'timing',
config: {
duration: scrollAnimationDuration,
easing: Easing.easeOutQuart,
},
(isFinished) => {
if (isFinished) {
onFinished?.();
}
}
};

return dealWithAnimation(withAnimation ?? defaultWithAnimation)(
toValue,
callback
);
},
[scrollAnimationDuration]
[scrollAnimationDuration, withAnimation]
);

const endWithSpring = React.useCallback(
Expand Down Expand Up @@ -234,7 +243,8 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
? translationX
: translationY;

endWithSpring(() => onScrollEnd && runOnJS(onScrollEnd)());
// endWithSpring(() => onScrollEnd && runOnJS(onScrollEnd)());
endWithSpring(onScrollEnd);

if (!infinite) {
touching.value = false;
Expand Down
Loading

0 comments on commit e3f34a4

Please sign in to comment.