Skip to content

Commit 9f53da2

Browse files
committed
add renderTrack prop
1 parent d71c7eb commit 9f53da2

File tree

4 files changed

+190
-30
lines changed

4 files changed

+190
-30
lines changed

example/src/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default function App() {
2626
<Examples.WithStep />
2727
<Examples.WithCache />
2828
<Examples.WithHaptic />
29+
<Examples.WithCustomTrack />
2930
<Examples.WithCustomBubble />
3031
<Examples.WithDisableTrack />
3132
<Examples.WithLottie />

example/src/sample/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { WithDisableTrack } from './src/with-disable-track';
66
import { WithHaptic } from './src/with-haptic';
77
import { WithLottie } from './src/with-lottie';
88
import { WithStep } from './src/with-step';
9+
import { WithCustomTrack } from './src/with-custom-track';
910

1011
export const Examples = {
1112
Basic,
@@ -16,6 +17,7 @@ export const Examples = {
1617
WithHaptic,
1718
WithLottie,
1819
WithStep,
20+
WithCustomTrack,
1921
};
2022

2123
export type ExampleType = keyof typeof Examples;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { Slider } from 'react-native-awesome-slider';
2+
import { StyleSheet, View } from 'react-native';
3+
import {
4+
SharedValue,
5+
useAnimatedStyle,
6+
useSharedValue,
7+
} from 'react-native-reanimated';
8+
import { COLORS } from './constants';
9+
import { SliderCard } from './components/slider-card';
10+
import Animated from 'react-native-reanimated';
11+
12+
const colors = [
13+
'#FF4B4B',
14+
'#FF764B',
15+
'#FFA14B',
16+
'#FFD24B',
17+
'#FFE74B',
18+
'#E9FF4B',
19+
'#BFFF4B',
20+
'#89FF4B',
21+
'#4BFF62',
22+
'#4BFFA1',
23+
];
24+
const step = colors.length - 1;
25+
26+
const TrackSegment = ({
27+
index,
28+
progress,
29+
step,
30+
color,
31+
}: {
32+
index: number;
33+
progress: SharedValue<number>;
34+
step: number;
35+
color: string | undefined;
36+
}) => {
37+
const style = useAnimatedStyle(() => {
38+
const progressStep = Math.round((progress.value / 100) * step);
39+
return {
40+
opacity: index < progressStep ? 1 : 0,
41+
};
42+
});
43+
44+
return (
45+
<View
46+
style={[
47+
styles.track,
48+
{
49+
borderTopLeftRadius: index === 0 ? 999 : 0,
50+
borderBottomLeftRadius: index === 0 ? 999 : 0,
51+
borderTopRightRadius: index === step ? 999 : 0,
52+
borderBottomRightRadius: index === step ? 999 : 0,
53+
overflow: 'hidden',
54+
},
55+
]}
56+
>
57+
<Animated.View style={[StyleSheet.absoluteFillObject, style]}>
58+
<View
59+
style={[StyleSheet.absoluteFillObject, { backgroundColor: color }]}
60+
/>
61+
</Animated.View>
62+
</View>
63+
);
64+
};
65+
66+
const sliderHeight = 8;
67+
68+
export function WithCustomTrack() {
69+
const progress = useSharedValue(50);
70+
const min = useSharedValue(0);
71+
const max = useSharedValue(100);
72+
73+
return (
74+
<SliderCard title="Custom tracks & marks">
75+
<Slider
76+
progress={progress}
77+
minimumValue={min}
78+
style={styles.slider}
79+
containerStyle={styles.containerStyle}
80+
maximumValue={max}
81+
steps={step}
82+
sliderHeight={sliderHeight}
83+
renderMark={({ index }) => {
84+
if (index === 0 || index === step) return null;
85+
return (
86+
<View
87+
style={[
88+
styles.mark,
89+
{
90+
backgroundColor: COLORS.markColor,
91+
},
92+
]}
93+
/>
94+
);
95+
}}
96+
renderTrack={({ index }) => {
97+
return (
98+
<TrackSegment
99+
index={index}
100+
progress={progress}
101+
step={step}
102+
color={colors[index]}
103+
/>
104+
);
105+
}}
106+
forceSnapToStep
107+
thumbWidth={20}
108+
theme={{
109+
...COLORS.sliderTheme,
110+
}}
111+
/>
112+
</SliderCard>
113+
);
114+
}
115+
116+
const styles = StyleSheet.create({
117+
slider: {
118+
marginBottom: 20,
119+
marginTop: 12,
120+
},
121+
containerStyle: {
122+
overflow: 'hidden',
123+
borderRadius: 999,
124+
},
125+
mark: {
126+
width: 2,
127+
height: sliderHeight,
128+
},
129+
track: {
130+
height: '100%',
131+
width: '100%',
132+
},
133+
});

src/slider.tsx

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,10 @@ export type AwesomeSliderProps = {
153153
* Render custom mark element. if you need to customize mark, you also need to set the `mark width`
154154
*/
155155
renderMark?: ({ index }: { index: number }) => React.ReactNode;
156-
156+
/**
157+
* Render custom track element. if you need to customize track, you also need to set the `mark width`
158+
*/
159+
renderTrack?: ({ index }: { index: number }) => React.ReactNode;
157160
/**
158161
* Thumb elements width, default 15
159162
*/
@@ -338,6 +341,7 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
338341
renderBubble,
339342
renderThumb,
340343
renderMark,
344+
renderTrack,
341345
setBubbleText,
342346
sliderHeight = 5,
343347
step: propsStep,
@@ -1042,36 +1046,52 @@ export const Slider: FC<AwesomeSliderProps> = memo(function Slider({
10421046
</Animated.View>
10431047
{sliderWidth > 0 && step
10441048
? new Array(step + 1).fill(0).map((_, i) => {
1045-
const left = Math.round(
1046-
sliderWidth * (i / step) - (i / step) * markWidth
1047-
);
1049+
const markLeft =
1050+
sliderWidth * (i / step) - (i / step) * markWidth;
1051+
const nextMarkLeft = sliderWidth * ((i + 1) / step);
10481052

1049-
return renderMark ? (
1050-
<View
1051-
key={i}
1052-
style={[
1053-
styles.customMarkContainer,
1054-
{
1055-
left,
1056-
width: markWidth,
1057-
},
1058-
]}
1059-
>
1060-
{renderMark({ index: i })}
1061-
</View>
1062-
) : (
1063-
<View
1064-
key={i}
1065-
style={[
1066-
styles.mark,
1067-
{
1068-
width: markWidth,
1069-
borderRadius: markWidth,
1070-
left,
1071-
},
1072-
markStyle,
1073-
]}
1074-
/>
1053+
return (
1054+
<React.Fragment key={i}>
1055+
{renderTrack && (
1056+
<View
1057+
style={[
1058+
styles.customTrackContainer,
1059+
{
1060+
left: markLeft,
1061+
width: nextMarkLeft - markLeft,
1062+
},
1063+
]}
1064+
>
1065+
{renderTrack({ index: i })}
1066+
</View>
1067+
)}
1068+
1069+
{renderMark ? (
1070+
<View
1071+
style={[
1072+
styles.customMarkContainer,
1073+
{
1074+
left: markLeft,
1075+
width: markWidth,
1076+
},
1077+
]}
1078+
>
1079+
{renderMark({ index: i })}
1080+
</View>
1081+
) : (
1082+
<View
1083+
style={[
1084+
styles.mark,
1085+
{
1086+
width: markWidth,
1087+
borderRadius: markWidth,
1088+
left: markLeft,
1089+
},
1090+
markStyle,
1091+
]}
1092+
/>
1093+
)}
1094+
</React.Fragment>
10751095
);
10761096
})
10771097
: null}
@@ -1158,4 +1178,8 @@ const styles = StyleSheet.create({
11581178
bubble: {
11591179
position: 'absolute',
11601180
},
1181+
customTrackContainer: {
1182+
position: 'absolute',
1183+
height: '100%',
1184+
},
11611185
});

0 commit comments

Comments
 (0)