I'm currently creating a step bar animation that has this sort of functionality with a FlatList
for the bar's percentage. ( I used this youtube tutorial for reference https://www.youtube.com/watch?v=SLbay2efwso )
in between the bars there are going to be numbers for the steps i.e (1)---(2)---etc.
I've implemented this using react-native
's Animated
library and react-native-svg
for the <Line/>
tag but as you can see the animation is slow. If I speed up the duration in the timing function then sometimes the animation doesn't complete the full length of the bar and you'll see a small portion of the darker bar underneath. Is there a better way I should go about this functionality?
Here's the code:
import React, { useEffect, useRef } from 'react'
import { View, Text, Animated } from 'react-native'
import Svg, {Line} from 'react-native-svg';
const ProgressBar = ({ percentage }) => {
const progressAnimation = useRef(new Animated.Value(0)).current;
const progressAnimation2 = useRef(new Animated.Value(0)).current;
const progressAnimation3 = useRef(new Animated.Value(0)).current;
const progressRef1 = useRef(null);
const progressRef2 = useRef(null);
const progressRef3 = useRef(null);
const animation1 = (toValue) => {
return Animated.timing(progressAnimation, {
toValue,
duration: 250,
useNativeDriver: true
}).start();
};
const animation2 = (toValue) => {
return Animated.timing(progressAnimation2, {
toValue,
duration: 250,
useNativeDriver: true
}).start();
};
const animation3 = (toValue) => {
return Animated.timing(progressAnimation3, {
toValue,
duration: 250,
useNativeDriver: true
}).start();
};
useEffect(()=>{
animation1(percentage)
animation2(percentage)
animation3(percentage)
}, [percentage])
useEffect(() =>{
progressAnimation.addListener(
(value) => {
const strokeDashoffset = 100 - (10000 * value.value)/100;
if (progressRef1?.current && value.value <1) {
progressRef1.current.setNativeProps({
strokeDashoffset
})
}
},
[percentage]
);
progressAnimation2.addListener(
(value) => {
const strokeDashoffset = 200 - (10000 * value.value)/100;
if (progressRef2?.current && value.value >= 1 && value.value < 2) {
progressRef2.current.setNativeProps({
strokeDashoffset
})
}
},
[percentage]
);
progressAnimation3.addListener(
(value) => {
const strokeDashoffset = 300 - (10000 * value.value)/100;
console.log(strokeDashoffset)
if (progressRef3?.current && value.value >= 2 && value.value < 3) {
progressRef3.current.setNativeProps({
strokeDashoffset
})
}
},
[percentage]
);
})
return (
<View style={{height: 5, justifyContent:'center', alignItems:'center'}}>
<Svg height="4" width="80%">
<Line
x1="0"
y1="0"
x2="33%"
y2="0"
stroke="#2f3a4c"
strokeWidth="4"/>
<Line
x1="0"
y1="0"
x2="33%"
y2="0"
stroke="#F4338F"
strokeWidth="4"
strokeDasharray={100}
ref={progressRef1}/>
<Line
x1="35%"
y1="0"
x2="63%"
y2="0"
stroke="#2f3a4c"
strokeWidth="4"/>
<Line
x1="35%"
y1="0"
x2="63%"
y2="0"
stroke="#F4338F"
strokeWidth="4"
strokeDasharray={100}
strokeDashoffset={100}
ref={progressRef2}/>
<Line
x1="65%"
y1="0"
x2="99%"
y2="0"
stroke="#2f3a4c"
strokeWidth="4"/>
<Line
x1="65%"
y1="0"
x2="99%"
y2="0"
stroke="#F4338F"
strokeWidth="4"
strokeDasharray={100}
strokeDashoffset={100}
ref={progressRef3}/>
</Svg>
</View>
)
}
export default ProgressBar