1+ import React , { useRef , useState , useEffect } from 'react' ;
2+ import {
3+ Animated ,
4+ View ,
5+ StyleSheet ,
6+ ViewProps ,
7+ LayoutChangeEvent
8+ } from 'react-native'
9+
10+ type PositionType = 'fixed' | 'relative'
11+
12+ // 组件的属性定义
13+ export interface ProgressProps extends ViewProps {
14+ /** 当前进度百分比, 0 - 100, 默认0 */
15+ progress ?: number ;
16+ /** 颜色 */
17+ progressColor ? : string
18+ /** 位置 */
19+ position ?: PositionType ;
20+ /** 动画持续的时间 */
21+ animation ?: { duration ?: number ; } | boolean ;
22+ }
23+
24+ export default ( props : ProgressProps ) => {
25+ const {
26+ style,
27+ progress = 0 ,
28+ progressColor = '#108ee9' ,
29+ position,
30+ animation = { duration : 500 } ,
31+ } = props ;
32+
33+ const progWidth = useRef < any > ( new Animated . Value ( 0 ) ) . current ;
34+ const [ wrapWidth , setWrapWidth ] = useState < number > ( 0 ) ;
35+
36+ useEffect ( ( ) => {
37+ startAnimation ( ) ;
38+ } , [ wrapWidth , progress ] )
39+
40+ const startAnimation = ( ) => {
41+ Animated . timing ( progWidth , {
42+ toValue : getWidth ( ) ,
43+ duration : typeof animation !== 'boolean' ? animation . duration : 1000 ,
44+ useNativeDriver : false ,
45+ } ) . start ( ) ;
46+ } ;
47+
48+ const onLayout = ( e : LayoutChangeEvent ) => {
49+ setWrapWidth ( e . nativeEvent . layout . width ) ;
50+ }
51+
52+ const getWidth = ( percent : number = progress ) => {
53+ return wrapWidth * ( normalPercent ( percent ) / 100 )
54+ }
55+
56+ const normalPercent = ( percent ?: number ) => {
57+ let widthPercent : any = 0
58+ if ( percent !== undefined && percent > 0 ) {
59+ widthPercent = percent > 100 ? 100 : percent
60+ }
61+ return widthPercent
62+ }
63+
64+ return (
65+ < View style = { [ styles . container , style ] } >
66+ < View onLayout = { onLayout } style = { [
67+ styles . pre ,
68+ position === 'fixed' ? { position : 'absolute' , top : 0 } : { } ,
69+ { borderColor : progressColor } ] } >
70+ < Animated . View
71+ style = { [ styles . preOisn , {
72+ width : progWidth ,
73+ backgroundColor : progressColor
74+ } ] } > </ Animated . View >
75+ </ View >
76+ </ View >
77+ )
78+ }
79+
80+ const styles = StyleSheet . create ( {
81+ container : {
82+ position : 'relative' ,
83+ flex : 1 ,
84+ } ,
85+ pre : {
86+ borderWidth : 1 ,
87+ height : 4 ,
88+ width : '100%' ,
89+ borderRadius : 20 ,
90+ marginBottom : 0 ,
91+ marginTop : 0 ,
92+ overflow : 'hidden' ,
93+ } ,
94+ preOisn : {
95+ position : 'absolute' ,
96+ height : 4 ,
97+ left : 0 ,
98+ top : 0 ,
99+ } ,
100+ } ) ;
0 commit comments