66 行
1.6 KiB
TypeScript
66 行
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,
|
|
},
|
|
})
|