So below is my code trying to make an animation bar
const ProgressBarInternal = ({
color,
backgroundColor,
style,
height,
animDuration,
total,
progress,
testID = 'progress-bar',
borderRadius,
containerHeight,
onAnimationDidEnd,
}: Props): JSX.Element => {
const barProgressPercentageNum = Math.max(0, Math.floor((progress / total) * 100))
const barProgressPercentageString = `${barProgressPercentageNum}%`
const translateX = useRef(new Animated.Value(0))
useEffect(() => {
Animated.timing(translateX.current, {
toValue: 1,
duration: animDuration || 950,
easing: Easing.inOut(Easing.ease),
}).start(() => onAnimationDidEnd)
}, [])
return (
<View
testID={testID}
style={[
styles.container,
{ borderRadius: borderRadius, height: containerHeight },
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{ borderRadius: borderRadius },
{
backgroundColor: color,
width: barProgressPercentageString,
},
{
transform: [
{
translateX: translateX.current.interpolate({
inputRange: [0, 1],
outputRange: ['0%', '100%'],
}),
},
],
},
]}
/>
</View>
)
}
with above code, it does animation in a strange way -> moved the bar to the center of the bar holder
what I expect to get is something like this :
I think it is something to do with my translateX not setting up correctly? Please advise with some code sample Thanks
Edited
Following Marek's suggestions: I now have :
const ProgressBarInternal = ({
color,
backgroundColor,
style,
height,
animDuration,
total,
progress,
testID = 'progress-bar',
borderRadius,
containerHeight,
onAnimationDidEnd,
}: Props): JSX.Element => {
const barProgressPercentageNum = Math.max(0, Math.floor((progress / total) * 100))
const barProgressPercentageString = `${barProgressPercentageNum}%`
const animation = useRef(new Animated.Value(0))
useEffect(() => {
Animated.timing(translateX.current, {
toValue: 1 ,
duration: animDuration || 950,
easing: Easing.inOut(Easing.ease),
}).start(() => onAnimationDidEnd)
}, [])
return (
<View
testID={testID}
style={[
styles.container,
{ borderRadius: borderRadius, height: containerHeight },
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{ borderRadius: borderRadius },
{
backgroundColor: color,
//how do I pass my param -> barProgressPercentageNum to here?
width: animation.current.interpolate({ inputRange: [0, 1], outputRange: ['0%', '100%']}),
},
]}
/>
</View>
)
}
I wish to pass in a width % param to the bar, so it only animate to my requested position, how would I do that? Thanks
2nd Edited
Please see the edited code with container style and animated style
import React, { useEffect, useRef } from 'react'
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
import Animated, { Easing } from 'react-native-reanimated'
interface Props {
total: number
progress: number
color?: string
backgroundColor?: string
height?: number
style?: StyleProp<ViewStyle>
animDelay?: number
animDuration?: number
testID?: string
borderRadius?: number
containerHeight?: number
onAnimationDidEnd?: () => void
}
const ProgressBarInternal = ({
color,
backgroundColor,
style,
height,
animDuration,
total,
progress,
testID = 'progress-bar',
borderRadius,
containerHeight,
onAnimationDidEnd,
}: Props): JSX.Element => {
const barProgressPercentageNum = Math.max(0, Math.floor((progress / total) * 100))
const barProgressPercentageString = `${barProgressPercentageNum}%`
const translateX = useRef(new Animated.Value(0))
useEffect(() => {
Animated.timing(translateX.current, {
toValue: 1,
duration: animDuration || 950,
easing: Easing.inOut(Easing.ease),
}).start(() => onAnimationDidEnd)
}, [])
return (
<View
testID={testID}
style={[
styles.container,
{ borderRadius: borderRadius, height: containerHeight },
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{ borderRadius: borderRadius },
{
backgroundColor: color,
width: translateX.current.interpolate({ inputRange: [0, 1], outputRange: ['0%', '100%']}),
},
]}
/>
</View>
)
}
export default ProgressBarInternal
const styles = StyleSheet.create({
bar: {
height: '100%',
width: '100%',
},
container: {
flexDirection: 'row',
overflow: 'hidden',
width: '100%',
},
})
It only fills 1/3 of the bar even I set to 100%...