Skip to content

Commit 82f7b2a

Browse files
authored
Merge pull request #90 from dohooo/feat/render-item-context
feat: pass animation value to renderItem
2 parents eb3082b + fdc0f9e commit 82f7b2a

File tree

23 files changed

+589
-35
lines changed

23 files changed

+589
-35
lines changed

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ English | [简体中文](./README.zh-CN.md)
1313

1414
## ReactNative community's best use of the carousel component! 🎉🎉🎉
1515

16-
- **It completely solves this [problem](https://github.com/meliorence/react-native-snap-carousel/issues/632) for `react-native-snap-carousel`!**
16+
- **It completely solves this** [[problem]](https://github.com/meliorence/react-native-snap-carousel/issues/632) **for `react-native-snap-carousel`!**
1717
- **Simple****Infinitely scrolling very smooth****Fully implemented using Reanimated 2!**
1818

19-
> V2 has been released! Joint it! [V1 docs](https://github.com/dohooo/react-native-reanimated-carousel/tree/v1.x.x)
19+
> v2 has been released! Join it! [[v1 docs]](https://github.com/dohooo/react-native-reanimated-carousel/tree/v1.x.x)
2020
21-
> Click on the image to see the demo. [Try it(Snack)](https://snack.expo.dev/@zhaodonghao586/simple-carousel) 🍺
21+
> Click on the image to see the demo. [[Try it]](https://snack.expo.dev/@zhaodonghao586/simple-carousel) 🍺
2222
2323
<p align="center">
2424
<a href="./example/src/normal/index.tsx">
@@ -47,7 +47,16 @@ English | [简体中文](./README.zh-CN.md)
4747
</a>
4848
</p>
4949

50-
<br/>
50+
> Now you can make cool animations with us! Very easy! [[Details]](./docs/custom-animation.md)
51+
52+
<p align="center">
53+
<a href="./example/src/advanced-parallax/index.tsx">
54+
<img src="assets/advanced-parallax.gif" width="300"/>
55+
</a>
56+
<a href="./example/src/scale-fade-in-out/index.tsx">
57+
<img src="assets/scale-fade-in-out.gif" width="300"/>
58+
</a>
59+
</p>
5160

5261
## Table of contents
5362

@@ -83,7 +92,7 @@ import Carousel from 'react-native-reanimated-carousel';
8392
width={300}
8493
height={150}
8594
data={[1, 2, 3]}
86-
renderItem={(item) => <AnyElement />}
95+
renderItem={({ item }) => <AnyElement />}
8796
/>;
8897
```
8998

README.zh-CN.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313

1414
## ReactNative 社区最好用的轮播图组件! 🎉🎉🎉
1515

16-
- **完全解决了`react-native-snap-carousel`[问题](https://github.com/meliorence/react-native-snap-carousel/issues/632)**
16+
- **完全解决了`react-native-snap-carousel`** [[问题]](https://github.com/meliorence/react-native-snap-carousel/issues/632)
1717
- **易用****无限滚动****完全使用 Reanimated2 实现**
1818

19-
> V2 已经发布,希望大家喜欢~ [V1 文档](https://github.com/dohooo/react-native-reanimated-carousel/tree/v1.x.x)
19+
> v2 已经发布,希望大家喜欢!~ [[v1 文档]](https://github.com/dohooo/react-native-reanimated-carousel/tree/v1.x.x)
2020
21-
> 点击图片,查看 demo。[试一下(Snack)](https://snack.expo.dev/@zhaodonghao586/simple-carousel) 🍺
21+
> 点击图片,查看 demo。[[试一下]](https://snack.expo.dev/@zhaodonghao586/simple-carousel) 🍺
2222
2323
<p align="center">
2424
<a href="./example/src/normal/index.tsx">
@@ -47,7 +47,17 @@
4747
</a>
4848
</p>
4949

50-
<br/>
50+
51+
> 现在你可以和我们一起来制作酷炫的动画了! 非常简单! [[详情]](./docs/custom-animation.zh-CN.md)
52+
53+
<p align="center">
54+
<a href="./example/src/advanced-parallax/index.tsx">
55+
<img src="assets/advanced-parallax.gif" width="300"/>
56+
</a>
57+
<a href="./example/src/scale-fade-in-out/index.tsx">
58+
<img src="assets/scale-fade-in-out.gif" width="300"/>
59+
</a>
60+
</p>
5161

5262
## 目录
5363

@@ -85,7 +95,7 @@ import Carousel from 'react-native-reanimated-carousel';
8595
width={300}
8696
height={150}
8797
data={[1, 2, 3]}
88-
renderItem={(item) => <AnyElement />}
98+
renderItem={({ item }) => <AnyElement />}
8999
/>;
90100
```
91101

assets/advanced-parallax.gif

3.78 MB
Loading

assets/scale-fade-in-out.gif

1.45 MB
Loading

docs/custom-animation.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
## Custom Animation
2+
3+
After some effort, we finally implemented custom animation in v2, now we just need to implement a callback function of type `TAnimationStyle` and pass it to the `customAnimation` property of `Carousel`.
4+
5+
Here are a few examples for you.
6+
7+
### Parallax
8+
9+
<a href="../example/src/advanced-parallax/index.tsx">
10+
<img src="././../assets/advanced-parallax.gif" width="300"/>
11+
</a>
12+
13+
```ts
14+
const animationStyle: TAnimationStyle = React.useCallback(
15+
(value: number) => {
16+
'worklet';
17+
18+
const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
19+
const translateX = interpolate(
20+
value,
21+
[-2, 0, 1],
22+
[-PAGE_WIDTH, 0, PAGE_WIDTH]
23+
);
24+
25+
return {
26+
transform: [{ translateX }],
27+
zIndex,
28+
};
29+
},
30+
[]
31+
);
32+
33+
<Carousel
34+
style={{ width: screen.width, height: 240 }}
35+
width={screen.width}
36+
data={[...new Array(6).keys()]}
37+
customAnimation={animationStyle}
38+
renderItem={({ index, animationValue }) => {
39+
return (
40+
<CustomItem
41+
key={index}
42+
index={index}
43+
animationValue={animationValue}
44+
/>
45+
);
46+
}}
47+
/>
48+
49+
const CustomItem = ({ index, animationValue }) => {
50+
const maskStyle = useAnimatedStyle(() => {
51+
const backgroundColor = interpolateColor(
52+
animationValue.value,
53+
[-1, 0, 1],
54+
['#000000dd', 'transparent', '#000000dd']
55+
);
56+
57+
return {
58+
backgroundColor,
59+
};
60+
}, [animationValue]);
61+
62+
return (
63+
<View style={{ flex: 1 }}>
64+
<SBItem key={index} index={index} style={{ borderRadius: 0 }} />
65+
<Animated.View
66+
pointerEvents="none"
67+
style={[
68+
{
69+
position: 'absolute',
70+
top: 0,
71+
left: 0,
72+
right: 0,
73+
bottom: 0,
74+
},
75+
maskStyle,
76+
]}
77+
/>
78+
</View>
79+
);
80+
}
81+
```
82+
83+
In order to implement some animation effects outside `Carousel`, such as `MaskView`, we pass the animation value calculated inside each Item to the outside through `renderItem`.
84+
85+
### ScaleFadeInOut
86+
87+
<a href="../example/src/scale-fade-in-out/index.tsx">
88+
<img src="././../assets/scale-fade-in-out.gif" width="300"/>
89+
</a>
90+
91+
```ts
92+
const animationStyle: TAnimationStyle = React.useCallback(
93+
(value: number) => {
94+
'worklet';
95+
96+
const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
97+
const scale = interpolate(value, [-1, 0, 1], [1.25, 1, 0.25]);
98+
const opacity = interpolate(value, [-0.75, 0, 1], [0, 1, 0]);
99+
100+
return {
101+
transform: [{ scale }],
102+
zIndex,
103+
opacity,
104+
};
105+
},
106+
[]
107+
);
108+
109+
<Carousel
110+
style={{
111+
width: screen.width,
112+
height: 240,
113+
justifyContent: 'center',
114+
alignItems: 'center',
115+
}}
116+
width={screen.width * 0.7}
117+
height={240 * 0.7}
118+
data={[...new Array(6).keys()]}
119+
customAnimation={animationStyle}
120+
renderItem={({ index }) => {
121+
return (
122+
<SBItem
123+
key={index}
124+
index={index}
125+
style={{
126+
borderWidth: 5,
127+
borderColor: Colors.orange50,
128+
}}
129+
/>
130+
);
131+
}}
132+
/>
133+
```

docs/custom-animation.zh-CN.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
## 自定义动画
2+
3+
经过一些努力,我们终于在v2版本中实现了自定义动画,现在只需实现一个类型`TAnimationStyle`的回调函数,然后将它传给`Carousel``customAnimation`属性即可。
4+
5+
下面给大家带来几个例子。
6+
7+
### 视差效果
8+
9+
<a href="../example/src/advanced-parallax/index.tsx">
10+
<img src="././../assets/advanced-parallax.gif" width="300"/>
11+
</a>
12+
13+
```ts
14+
const animationStyle: TAnimationStyle = React.useCallback(
15+
(value: number) => {
16+
'worklet';
17+
18+
const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
19+
const translateX = interpolate(
20+
value,
21+
[-2, 0, 1],
22+
[-PAGE_WIDTH, 0, PAGE_WIDTH]
23+
);
24+
25+
return {
26+
transform: [{ translateX }],
27+
zIndex,
28+
};
29+
},
30+
[]
31+
);
32+
33+
<Carousel
34+
style={{ width: screen.width, height: 240 }}
35+
width={screen.width}
36+
data={[...new Array(6).keys()]}
37+
customAnimation={animationStyle}
38+
renderItem={({ index, animationValue }) => {
39+
return (
40+
<CustomItem
41+
key={index}
42+
index={index}
43+
animationValue={animationValue}
44+
/>
45+
);
46+
}}
47+
/>
48+
49+
const CustomItem = ({ index, animationValue }) => {
50+
const maskStyle = useAnimatedStyle(() => {
51+
const backgroundColor = interpolateColor(
52+
animationValue.value,
53+
[-1, 0, 1],
54+
['#000000dd', 'transparent', '#000000dd']
55+
);
56+
57+
return {
58+
backgroundColor,
59+
};
60+
}, [animationValue]);
61+
62+
return (
63+
<View style={{ flex: 1 }}>
64+
<SBItem key={index} index={index} style={{ borderRadius: 0 }} />
65+
<Animated.View
66+
pointerEvents="none"
67+
style={[
68+
{
69+
position: 'absolute',
70+
top: 0,
71+
left: 0,
72+
right: 0,
73+
bottom: 0,
74+
},
75+
maskStyle,
76+
]}
77+
/>
78+
</View>
79+
);
80+
}
81+
```
82+
83+
为了让`Carousel`外部实现一些动画效果,比如`MaskView`,我们将每个Item内部计算出来的动画值通过`renderItem`传递到了外部。
84+
85+
### 缩放渐入渐出效果
86+
87+
<a href="../example/src/scale-fade-in-out/index.tsx">
88+
<img src="././../assets/scale-fade-in-out.gif" width="300"/>
89+
</a>
90+
91+
```ts
92+
const animationStyle: TAnimationStyle = React.useCallback(
93+
(value: number) => {
94+
'worklet';
95+
96+
const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
97+
const scale = interpolate(value, [-1, 0, 1], [1.25, 1, 0.25]);
98+
const opacity = interpolate(value, [-0.75, 0, 1], [0, 1, 0]);
99+
100+
return {
101+
transform: [{ scale }],
102+
zIndex,
103+
opacity,
104+
};
105+
},
106+
[]
107+
);
108+
109+
<Carousel
110+
style={{
111+
width: screen.width,
112+
height: 240,
113+
justifyContent: 'center',
114+
alignItems: 'center',
115+
}}
116+
width={screen.width * 0.7}
117+
height={240 * 0.7}
118+
data={[...new Array(6).keys()]}
119+
customAnimation={animationStyle}
120+
renderItem={({ index }) => {
121+
return (
122+
<SBItem
123+
key={index}
124+
index={index}
125+
style={{
126+
borderWidth: 5,
127+
borderColor: Colors.orange50,
128+
}}
129+
/>
130+
);
131+
}}
132+
/>
133+
```

docs/props.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
| name | required | default | types | description |
44
| ---------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
55
| data || | T[] | Carousel items data set |
6-
| renderItem || | (data: T, index: number) => React.ReactNode | Render carousel item |
6+
| renderItem || | (info: { data: T, index: number, animationValue: SharedValue\<number> }) => React.ReactElement | Render carousel item |
77
| vertical || false | boolean | Layout items vertically instead of horizontally |
88
| width | vertical ❌ horizontal ✅ | '100%' | number \| undefined | Specified carousel item width |
99
| height | vertical ✅ horizontal ❌ | '100%' | number \| undefined | Specified carousel item height |
@@ -26,7 +26,7 @@
2626
| pagingEnabled || true | boolean | When true, the scroll view stops on multiples of the scroll view's size when scrolling |
2727
| enableSnap || true | boolean | If enabled, releasing the touch will scroll to the nearest item, valid when pagingEnabled=false |
2828
| customConfig || | () => {type?: 'negative' \| 'positive';viewCount?: number;} | Custom carousel config |
29-
| customAnimation || | (value: number) => Animated.AnimatedStyleProp<ViewStyle> | Custom animations. For details, see below[modeConfig](todo) |
29+
| customAnimation || | (value: number) => Animated.AnimatedStyleProp<ViewStyle> | Custom animations. For details, see below[custom animation](./custom-animation.md) |
3030

3131
## `modeConfig` Props
3232

0 commit comments

Comments
 (0)