1

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 )

enter image description here

in between the bars there are going to be numbers for the steps i.e (1)---(2)---etc. enter image description here

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

0 Answers0