73 行
1.6 KiB
TypeScript
73 行
1.6 KiB
TypeScript
import React, { useEffect, useRef } from 'react'
|
|
import { Animated, Dimensions, StyleSheet, View } from 'react-native'
|
|
|
|
type Props = {
|
|
progress: number
|
|
visible: boolean
|
|
}
|
|
|
|
const SCREEN_WIDTH = Dimensions.get('window').width
|
|
|
|
const GRADIENT_COLORS = [
|
|
'#3b82f6',
|
|
'#6366f1',
|
|
'#8b5cf6',
|
|
'#a855f7',
|
|
'#ec4899',
|
|
'#f43f5e',
|
|
]
|
|
|
|
export default function XWebViewProgress({ progress, visible }: Props) {
|
|
const animWidth = useRef(new Animated.Value(0)).current
|
|
const animOpacity = useRef(new Animated.Value(0)).current
|
|
|
|
useEffect(() => {
|
|
Animated.timing(animOpacity, {
|
|
toValue: visible ? 1 : 0,
|
|
duration: visible ? 150 : 300,
|
|
useNativeDriver: false,
|
|
}).start()
|
|
}, [visible, animOpacity])
|
|
|
|
useEffect(() => {
|
|
Animated.timing(animWidth, {
|
|
toValue: Math.min(progress, 1) * SCREEN_WIDTH,
|
|
duration: 200,
|
|
useNativeDriver: false,
|
|
}).start()
|
|
}, [progress, animWidth])
|
|
|
|
return (
|
|
<Animated.View style={[styles.container, { opacity: animOpacity }]}>
|
|
<Animated.View style={[styles.track, { width: animWidth }]}>
|
|
<View style={styles.gradient}>
|
|
{GRADIENT_COLORS.map(color => (
|
|
<View key={color} style={[styles.segment, { backgroundColor: color }]} />
|
|
))}
|
|
</View>
|
|
</Animated.View>
|
|
</Animated.View>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
height: 3,
|
|
backgroundColor: '#e2e8f0',
|
|
overflow: 'hidden',
|
|
},
|
|
track: {
|
|
height: 3,
|
|
overflow: 'hidden',
|
|
},
|
|
gradient: {
|
|
flexDirection: 'row',
|
|
width: SCREEN_WIDTH,
|
|
height: 3,
|
|
},
|
|
segment: {
|
|
flex: 1,
|
|
height: 3,
|
|
},
|
|
})
|