admin管理员组文章数量:1387338
I am trying to build a progress bar for my react-native project It should be a generic ponent to be used in many places. Please see my code:
The progress bar tsx:
import React, { useEffect } from 'react'
import { Animated, StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
interface Props {
total: number
progress: number
color?: string
backgroundColor?: string
height?: number
style?: StyleProp<ViewStyle>
animDelay?: number
animDuration?: number
testID?: string
}
const ProgressBar = ({
color,
backgroundColor,
style,
height,
animDelay,
animDuration,
total,
progress,
testID = 'progress-bar',
}: Props): JSX.Element => {
const minWidthValue = 5.4
const percentage = total && progress ? Math.min(progress, total) / total : 0
const minDisplayWidth =
percentage > 0 && percentage < minWidthValue ? minWidthValue : percentage
const barWidth = `${Math.max(minDisplayWidth, Math.floor(percentage * 100))}%`
useEffect(() => {
const animationValue = new Animated.Value(0)
Animated.timing(animationValue, {
toValue: progress,
delay: animDelay,
duration: animDuration,
useNativeDriver: true,
}).start();
}, []);
return (
<View
testID={testID}
style={[
styles.container,
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{
backgroundColor: color,
width: barWidth,
},
]}
/>
</View>
)
}
export default ProgressBar
const BORDER_RADIUS = 15
const styles = StyleSheet.create({
bar: {
borderRadius: BORDER_RADIUS,
height: '100%',
},
container: {
borderRadius: BORDER_RADIUS,
flexDirection: 'row',
height: 30,
overflow: 'hidden',
width: '100%',
},
})
And the example of usesage, say on home.tsx:
<ProgressBarWrapper total={100} progress={50} testID='test-id-test-1' />
So what happen is, the total length(100%) , and I wish the animation moving from 0 to 50 in the bar at beginning when this ponent loaded up
With above code, I only get a static bar , not moving at all.. Could someone point me out where I have done wrong? Sample code would be very helpful Cheers
Edited:
I have updated code
useNativeDriver
and use interpolation
here to avoid oscillations using 'clamp'
However, the animation still not moving/working , wondering any advise on this. Thanks
const ProgressBarInternal = ({
color,
backgroundColor,
style,
height,
animDelay,
animDuration,
total,
progress,
testID = 'progress-bar',
borderRadius,
containerHeight,
onAnimationDidEnd,
}: Props): JSX.Element => {
const minWidthValue = 5.4
const percentage = total && progress ? Math.min(progress, total) / total : 0
const minDisplayWidth =
percentage > 0 && percentage < minWidthValue ? minWidthValue : percentage
const progressingBarWidthPercentage = `${Math.max(minDisplayWidth, Math.floor(percentage * 100))}%`
const animatingProgressBar = useRef(new Animated.Value(0))
useEffect(() => {
Animated.timing(animatingProgressBar.current, {
toValue: 0,
delay: animDelay,
duration: animDuration,
useNativeDriver: true,
}).start()
}, []
);
return (
<View
testID={testID}
style={...}>
<Animated.View
style={[
styles.bar,
{ borderRadius: borderRadius },
{
backgroundColor: color,
width: progressingBarWidthPercentage,
},
{
transform: [
{
translateX: animatingProgressBar.current.interpolate({
inputRange: [1, 100],
outputRange: ["0%", "100%"],
extrapolate: "clamp"
}),
},
],
},
]}
/>
</View>
)
}
I am trying to build a progress bar for my react-native project It should be a generic ponent to be used in many places. Please see my code:
The progress bar tsx:
import React, { useEffect } from 'react'
import { Animated, StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
interface Props {
total: number
progress: number
color?: string
backgroundColor?: string
height?: number
style?: StyleProp<ViewStyle>
animDelay?: number
animDuration?: number
testID?: string
}
const ProgressBar = ({
color,
backgroundColor,
style,
height,
animDelay,
animDuration,
total,
progress,
testID = 'progress-bar',
}: Props): JSX.Element => {
const minWidthValue = 5.4
const percentage = total && progress ? Math.min(progress, total) / total : 0
const minDisplayWidth =
percentage > 0 && percentage < minWidthValue ? minWidthValue : percentage
const barWidth = `${Math.max(minDisplayWidth, Math.floor(percentage * 100))}%`
useEffect(() => {
const animationValue = new Animated.Value(0)
Animated.timing(animationValue, {
toValue: progress,
delay: animDelay,
duration: animDuration,
useNativeDriver: true,
}).start();
}, []);
return (
<View
testID={testID}
style={[
styles.container,
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{
backgroundColor: color,
width: barWidth,
},
]}
/>
</View>
)
}
export default ProgressBar
const BORDER_RADIUS = 15
const styles = StyleSheet.create({
bar: {
borderRadius: BORDER_RADIUS,
height: '100%',
},
container: {
borderRadius: BORDER_RADIUS,
flexDirection: 'row',
height: 30,
overflow: 'hidden',
width: '100%',
},
})
And the example of usesage, say on home.tsx:
<ProgressBarWrapper total={100} progress={50} testID='test-id-test-1' />
So what happen is, the total length(100%) , and I wish the animation moving from 0 to 50 in the bar at beginning when this ponent loaded up
With above code, I only get a static bar , not moving at all.. Could someone point me out where I have done wrong? Sample code would be very helpful Cheers
Edited:
I have updated code
useNativeDriver
and use interpolation
here to avoid oscillations using 'clamp'
However, the animation still not moving/working , wondering any advise on this. Thanks
const ProgressBarInternal = ({
color,
backgroundColor,
style,
height,
animDelay,
animDuration,
total,
progress,
testID = 'progress-bar',
borderRadius,
containerHeight,
onAnimationDidEnd,
}: Props): JSX.Element => {
const minWidthValue = 5.4
const percentage = total && progress ? Math.min(progress, total) / total : 0
const minDisplayWidth =
percentage > 0 && percentage < minWidthValue ? minWidthValue : percentage
const progressingBarWidthPercentage = `${Math.max(minDisplayWidth, Math.floor(percentage * 100))}%`
const animatingProgressBar = useRef(new Animated.Value(0))
useEffect(() => {
Animated.timing(animatingProgressBar.current, {
toValue: 0,
delay: animDelay,
duration: animDuration,
useNativeDriver: true,
}).start()
}, []
);
return (
<View
testID={testID}
style={...}>
<Animated.View
style={[
styles.bar,
{ borderRadius: borderRadius },
{
backgroundColor: color,
width: progressingBarWidthPercentage,
},
{
transform: [
{
translateX: animatingProgressBar.current.interpolate({
inputRange: [1, 100],
outputRange: ["0%", "100%"],
extrapolate: "clamp"
}),
},
],
},
]}
/>
</View>
)
}
Share
Improve this question
edited Mar 26, 2021 at 18:52
sefirosu
asked Mar 25, 2021 at 14:32
sefirosusefirosu
2,65811 gold badges45 silver badges74 bronze badges
1
- did you find solution? if yes, I will happy if you can share – Manspof Commented Apr 20, 2022 at 22:50
2 Answers
Reset to default 3I encountered similar behavior when useNativeDriver was set to true.
Changing useNativeDriver to false may fix your issue
Also here is an example of how I achieved animated width:
const barWidth = useRef(new Animated.Value(0)).current;
const progressPercent = barWidth.interpolate({
inputRange: [0, 100],
outputRange: ["0%", `100%`],
});
useEffect(() => {
animatedController.setValue(0)
Animated.timing(barWidth, {
duration: 5000,
toValue: 100,
useNativeDriver: false
}).start();
}, [])
return (
<View style={...}>
<Animated.View
style={[
styles.bar,
{
backgroundColor: color,
width: progressPercent,
}
]}
/>
</View>
)
You can not animate with the width property.
Use transform instead.
An example with the base of your code.
import React, { useEffect, useRef } from 'react'
import { Animated, StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
interface Props {
total: number
progress: number
color?: string
backgroundColor?: string
height?: number
style?: StyleProp<ViewStyle>
animDelay?: number
animDuration?: number
testID?: string
}
const Test = ({
color,
backgroundColor,
style,
height,
animDelay,
animDuration,
total,
progress,
testID = 'progress-bar',
}: Props): JSX.Element => {
//const minWidthValue = 5.4
//const percentage = total && progress ? Math.min(progress, total) / total : 0
//const minDisplayWidth =
// percentage > 0 && percentage < minWidthValue ? minWidthValue : percentage
//const barWidth = `${Math.max(minDisplayWidth, Math.floor(percentage * 100))}%`
const barWidth = useRef(new Animated.Value(1)).current;
useEffect(() => {
//const animationValue = new Animated.Value(0)
Animated.timing(barWidth, {
toValue: 9,//progress,
//delay: 1000,//animDelay,
duration: 9000,//animDuration,
useNativeDriver: true,
}).start();
}, []
);
return (
<View
testID={testID}
style={[
styles.container,
height ? { height } : undefined,
backgroundColor ? { backgroundColor } : undefined,
style,
]}>
<Animated.View
style={[
styles.bar,
{
backgroundColor: color,
width: 50,
},
{transform: [{ scaleX: barWidth }]}
]}
/>
</View>
)
}
export default Test
const BORDER_RADIUS = 5
const styles = StyleSheet.create({
bar: {
borderRadius: BORDER_RADIUS,
height: '100%',
},
container: {
borderRadius: BORDER_RADIUS,
flexDirection: 'row',
height: 30,
overflow: 'hidden',
width: '100%',
},
})
本文标签: javascriptReact native animation progress barStack Overflow
版权声明:本文标题:javascript - React native animation progress bar - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744522306a2610528.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论