One approach将删除绝对位置,并使用flexbox将图像与行的末尾对齐:
const ProgressBar = ({imgSource,imgStyle,imgSize,style,progress,color})=>{
let loadingAnim = useRef(new Animated.Value(progress)).current;
const [{width,height},setViewDimensions] = useState({});
// get parent view size
const onLayout=({nativeEvent})=>{
setViewDimensions({
width:nativeEvent.layout.width,
height:nativeEvent.layout.height
})
}
const animatedWidth =loadingAnim.interpolate({
inputRange:[0,1],
outputRange:[0,width-imgSize],
extrapolate:'clamp'
})
const containerAnimation = {
margin:0,
padding:0,
width:Animated.add(animatedWidth,imgSize),
backgroundColor:color,
height:'100%',
justifyContent:'center',
overflow:'hidden'
}
useEffect(()=>{
Animated.timing(loadingAnim,{
toValue:progress,
duration:100
}).start()
},[progress])
return(
<View style={[styles.loadingContainer,{height:imgSize*1.5||null},style]} onLayout={onLayout}>
<Animated.View style={[styles.loadingContainer,containerAnimation]}>
<Animated.Image
source={imgSource}
style={[{height:imgSize,width:imgSize,alignSelf:'flex-end'},imgStyle,{}]}
/>
</Animated.View>
</View>
)
}
我发现这种方法有点不顺畅.我认为这是因为图像的父视图的宽度正在设置动画,而不是图像的实际位置.
Another approach将为图像设置动画:
const ProgressBar = ({imgSource,imgStyle,imgSize,style,progress,color})=>{
let widthAnim = useRef(new Animated.Value(progress)).current;
const [{width,height},setViewDimensions] = useState({});
// get parent view width to determine progress view size
const onLayout=({nativeEvent})=>{
setViewDimensions({
width:nativeEvent.layout.width,
height:nativeEvent.layout.height
})
}
const animatedWidth = widthAnim.interpolate({
inputRange:[0,1],
outputRange:[0,width-imgSize],
extrapolate:'clamp'
})
const containerAnimation = {
// min width will be imgSize
width:Animated.add(animatedWidth,imgSize),
backgroundColor:color,
}
const imgAnimation = {
left:animatedWidth
}
// animate progress changess
useEffect(()=>{
Animated.timing(widthAnim,{
toValue:progress,
duration:100
}).start()
},[progress])
return(
<View>
<View style={[styles.loadingContainer,{height:imgSize*1.25||null},style]} onLayout={onLayout}>
<Animated.View style={[styles.progressBar,containerAnimation]}/>
</View>
<Animated.Image
source={imgSource}
style={[styles.image,{height:imgSize,width:imgSize},imgStyle,imgAnimation]}
resizeMode='contain'
/>
</View>
)
}