1- import React , { Component , Fragment } from 'react' ;
1+ import React , { Fragment , useEffect , useState } from 'react' ;
22import {
33 Animated ,
44 StyleSheet ,
@@ -32,129 +32,10 @@ export interface DrawerState {
3232 isOpen : boolean ;
3333}
3434
35- export default class Drawer extends Component < DrawerProps , DrawerState > {
36- static defaultProps = {
37- placement : 'left' ,
38- drawerBackgroundColor : '#fff' ,
39- drawerWidth : 300 ,
40- drawerHeight : 500 ,
41- maskClosable : true ,
42- isOpen : false ,
43- onChange : ( ) => null ,
44- openDrawer : ( ) => null ,
45- closeDrawer : ( ) => null ,
46- } ;
47- constructor ( props : DrawerProps ) {
48- super ( props ) ;
49-
50- this . state = {
51- zIndexValue : 0 ,
52- overlayValue : new Animated . Value ( 0 ) ,
53- drawerValue : new Animated . ValueXY ( { ...this . getInitPosition ( ) } ) ,
54- isOpen : ! ! props . isOpen ,
55- } ;
56- }
57- handleDrawer = debounce ( ( isOpen : boolean ) => {
58- isOpen ? this . openDrawer ( ) : this . closeDrawer ( ) ;
59- } , 100 ) ;
60-
61- componentDidUpdate ( prevProps : DrawerProps , prevState : DrawerState ) {
62- if ( prevState . isOpen !== this . state . isOpen ) {
63- this . handleDrawer ( this . state . isOpen ) ;
64- }
65- if ( prevProps . isOpen !== this . props . isOpen ) {
66- this . handleDrawer ( ! ! this . props . isOpen ) ;
67- }
68- }
69- componentDidMount ( ) {
70- if ( this . props . isOpen ) {
71- this . openDrawer ( ) ;
72- }
73- }
74-
75- onOverlayClick = ( e : GestureResponderEvent ) => {
76- const { maskClosable } = this . props ;
77- if ( ! maskClosable ) {
78- return false ;
79- }
80- e . stopPropagation ( ) ;
81- this . closeDrawer ( ) ;
82- } ;
83- render ( ) {
84- const { style, drawerWidth, drawerBackgroundColor, maskProps, placement, drawerHeight } = this . props ;
85- const { isOpen, drawerValue, overlayValue, zIndexValue } = this . state ;
86- const isTopOrBottom = placement === 'top' || placement === 'bottom' ;
87- const changeStyle = isTopOrBottom ? 'height' : 'width' ;
88- const dynamicDrawerStyles : any = {
89- backgroundColor : drawerBackgroundColor ,
90- } ;
91-
92- if ( isTopOrBottom ) {
93- dynamicDrawerStyles . top = placement === 'top' ? 0 : null ;
94- dynamicDrawerStyles . bottom = placement === 'bottom' ? 0 : null ;
95- dynamicDrawerStyles . height = drawerWidth ;
96- dynamicDrawerStyles . width = '100%' ;
97- } else {
98- dynamicDrawerStyles . left = placement === 'left' ? 0 : null ;
99- dynamicDrawerStyles . right = placement === 'right' ? 0 : null ;
100- dynamicDrawerStyles . width = drawerWidth ;
101- }
102-
103- const overlayOpacity = overlayValue . interpolate ( {
104- inputRange : [ 0 , 1 ] ,
105- outputRange : [ 0 , 0.3 ] ,
106- extrapolate : 'clamp' ,
107- } ) ;
108- return (
109- < Fragment >
110- < Animated . View
111- style = { [
112- styles . drawer ,
113- dynamicDrawerStyles ,
114- style ,
115- // eslint-disable-next-line
116- {
117- [ changeStyle ] : isOpen ? ( isTopOrBottom ? drawerHeight : drawerWidth ) : 0 ,
118- transform : [
119- { translateX : drawerValue . x } , // x轴移动
120- { translateY : drawerValue . y } , // y轴移动
121- ] ,
122- } ,
123- ] }
124- >
125- { this . props . children }
126- </ Animated . View >
127- < Animated . View
128- pointerEvents = { isOpen ? 'auto' : 'none' }
129- style = { [
130- styles . overlay ,
131- styles . positionFull ,
132- maskProps ,
133- {
134- // opacity: overlayValue,
135- opacity : overlayOpacity ,
136- zIndex : zIndexValue ,
137- } ,
138- ] }
139- >
140- < TouchableOpacity
141- style = { [
142- styles . positionFull ,
143- // eslint-disable-next-line
144- {
145- zIndex : 3003 ,
146- position : 'absolute' ,
147- } ,
148- ] }
149- onPress = { this . onOverlayClick . bind ( this ) }
150- />
151- </ Animated . View >
152- </ Fragment >
153- ) ;
154- }
155-
156- getInitPosition ( ) {
157- const { drawerWidth, placement, drawerHeight } = this . props ;
35+ export default function Drawer ( props : DrawerProps ) {
36+ console . log ( 333 ) ;
37+ const getInitPosition = ( ) => {
38+ const { drawerWidth, placement, drawerHeight } = props ;
15839 const xy = { x : 0 , y : 0 } ;
15940 if ( placement === 'left' ) {
16041 xy . x = - ( drawerWidth || 0 ) ;
@@ -169,30 +50,38 @@ export default class Drawer extends Component<DrawerProps, DrawerState> {
16950 xy . y = DEVICE_HEIGHT || 0 ;
17051 }
17152 return xy ;
172- }
173- openDrawer ( ) {
174- this . setState ( { zIndexValue : 3002 , isOpen : true } ) ;
53+ } ;
54+
55+ const [ state , setState ] = useState ( {
56+ zIndexValue : 0 ,
57+ overlayValue : new Animated . Value ( 0 ) ,
58+ drawerValue : new Animated . ValueXY ( { ...getInitPosition ( ) } ) ,
59+ isOpen : ! ! props . isOpen ,
60+ } ) ;
61+
62+ const openDrawer = ( ) => {
63+ setState ( { ...state , zIndexValue : 3002 , isOpen : true } ) ;
17564 Animated . parallel ( [
176- Animated . spring ( this . state . drawerValue , {
65+ Animated . spring ( state . drawerValue , {
17766 toValue : { x : 0 , y : 0 } ,
17867 overshootClamping : true ,
17968 useNativeDriver : true ,
18069 } ) ,
181- Animated . spring ( this . state . overlayValue , {
70+ Animated . spring ( state . overlayValue , {
18271 toValue : 0.7 ,
18372 overshootClamping : true ,
18473 useNativeDriver : true ,
18574 } ) ,
18675 ] ) . start ( ( ) => {
187- this . props . openDrawer ! ( true ) ;
188- this . props . onChange ! ( true ) ;
76+ props . openDrawer ! ( true ) ;
77+ props . onChange ! ( true ) ;
18978 } ) ;
190- }
191- closeDrawer ( ) {
192- const { drawerValue, overlayValue } = this . state ;
79+ } ;
80+ const closeDrawer = ( ) => {
81+ const { drawerValue, overlayValue } = state ;
19382 Animated . parallel ( [
19483 Animated . spring ( drawerValue , {
195- toValue : { ...this . getInitPosition ( ) } ,
84+ toValue : { ...getInitPosition ( ) } ,
19685 overshootClamping : true ,
19786 useNativeDriver : true ,
19887 } ) ,
@@ -202,13 +91,124 @@ export default class Drawer extends Component<DrawerProps, DrawerState> {
20291 useNativeDriver : true ,
20392 } ) ,
20493 ] ) . start ( ( ) => {
205- this . props . closeDrawer ! ( false ) ;
206- this . props . onChange ! ( false ) ;
207- this . setState ( { zIndexValue : 0 , isOpen : false } ) ;
94+ props . closeDrawer ! ( false ) ;
95+ props . onChange ! ( false ) ;
96+ setState ( { ... state , zIndexValue : 0 , isOpen : false } ) ;
20897 } ) ;
98+ } ;
99+
100+ const handleDrawer = debounce ( ( isOpen : boolean ) => {
101+ isOpen ? openDrawer ( ) : closeDrawer ( ) ;
102+ } , 100 ) ;
103+
104+ useEffect ( ( ) => {
105+ handleDrawer ( state . isOpen ) ;
106+ } , [ state . isOpen ] ) ;
107+
108+ useEffect ( ( ) => {
109+ handleDrawer ( ! ! props . isOpen ) ;
110+ } , [ props . isOpen ] ) ;
111+
112+ useEffect ( ( ) => {
113+ if ( props . isOpen ) {
114+ openDrawer ( ) ;
115+ }
116+ } , [ ] ) ;
117+
118+ const onOverlayClick = ( e : GestureResponderEvent ) => {
119+ const { maskClosable } = props ;
120+ if ( ! maskClosable ) {
121+ return false ;
122+ }
123+ e . stopPropagation ( ) ;
124+ closeDrawer ( ) ;
125+ } ;
126+
127+ const { style, drawerWidth, drawerBackgroundColor, maskProps, placement, drawerHeight } = props ;
128+ const { isOpen, drawerValue, overlayValue, zIndexValue } = state ;
129+ const isTopOrBottom = placement === 'top' || placement === 'bottom' ;
130+ const changeStyle = isTopOrBottom ? 'height' : 'width' ;
131+ const dynamicDrawerStyles : any = {
132+ backgroundColor : drawerBackgroundColor ,
133+ } ;
134+
135+ if ( isTopOrBottom ) {
136+ dynamicDrawerStyles . top = placement === 'top' ? 0 : null ;
137+ dynamicDrawerStyles . bottom = placement === 'bottom' ? 0 : null ;
138+ dynamicDrawerStyles . height = drawerWidth ;
139+ dynamicDrawerStyles . width = '100%' ;
140+ } else {
141+ dynamicDrawerStyles . left = placement === 'left' ? 0 : null ;
142+ dynamicDrawerStyles . right = placement === 'right' ? 0 : null ;
143+ dynamicDrawerStyles . width = drawerWidth ;
209144 }
145+
146+ const overlayOpacity = overlayValue . interpolate ( {
147+ inputRange : [ 0 , 1 ] ,
148+ outputRange : [ 0 , 0.3 ] ,
149+ extrapolate : 'clamp' ,
150+ } ) ;
151+
152+ return (
153+ < Fragment >
154+ < Animated . View
155+ style = { [
156+ styles . drawer ,
157+ dynamicDrawerStyles ,
158+ style ,
159+ // eslint-disable-next-line
160+ {
161+ [ changeStyle ] : isOpen ? ( isTopOrBottom ? drawerHeight : drawerWidth ) : 0 ,
162+ transform : [
163+ { translateX : drawerValue . x } , // x轴移动
164+ { translateY : drawerValue . y } , // y轴移动
165+ ] ,
166+ } ,
167+ ] }
168+ >
169+ { props . children }
170+ </ Animated . View >
171+ < Animated . View
172+ pointerEvents = { isOpen ? 'auto' : 'none' }
173+ style = { [
174+ styles . overlay ,
175+ styles . positionFull ,
176+ maskProps ,
177+ {
178+ // opacity: overlayValue,
179+ opacity : overlayOpacity ,
180+ zIndex : zIndexValue ,
181+ } ,
182+ ] }
183+ >
184+ < TouchableOpacity
185+ style = { [
186+ styles . positionFull ,
187+ // eslint-disable-next-line
188+ {
189+ zIndex : 3003 ,
190+ position : 'absolute' ,
191+ } ,
192+ ] }
193+ onPress = { onOverlayClick }
194+ />
195+ </ Animated . View >
196+ </ Fragment >
197+ ) ;
210198}
211199
200+ Drawer . defaultProps = {
201+ placement : 'left' ,
202+ drawerBackgroundColor : '#fff' ,
203+ drawerWidth : 300 ,
204+ drawerHeight : 500 ,
205+ maskClosable : true ,
206+ isOpen : false ,
207+ onChange : ( ) => null ,
208+ openDrawer : ( ) => null ,
209+ closeDrawer : ( ) => null ,
210+ } as DrawerProps ;
211+
212212const styles = StyleSheet . create ( {
213213 drawer : {
214214 position : 'absolute' ,
0 commit comments