-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSwiper.js
126 lines (112 loc) · 3.63 KB
/
Swiper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React,{ Component } from 'react';
import { PanResponder, Animated } from 'react-native';
import PropTypes from 'prop-types';
export default class Swiper extends Component{
constructor(props){
super(props);
this.state = {
width: 0,
height: 0,
fadeAnimation: new Animated.Value(1),
moveAnimation: new Animated.ValueXY({x: 0, y: 0}),
};
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this.onPanStart,
onPanResponderMove: (e, gestureState) => this.positionChange(gestureState),
onPanResponderEnd: (e, gestureState) => this.endGesture(gestureState),
onShouldBlockNativeResponder: (e) => true,
onPanResponderTerminationRequest: () => false
});
}
onPanStart = () => {
const { enableParentScroll = false } = this.props;
enableParentScroll !== false && enableParentScroll(false);
return true;
}
positionChange = ({dx, dy}) => {
const { moveAnimation, fadeAnimation } = this.state;
Animated.spring(moveAnimation, {
toValue: {x: dx, y: dy},
}).start();
Animated.spring(fadeAnimation, {
toValue: 0.4
}).start();
}
endGesture = ({dx, dy}) => {
const { onSwipeUp, onSwipeDown, onSwipeLeft, onSwipeRight } = this.props;
const { width, height } = this.state;
const { swipeRatioX, swipeRatioY } = {swipeRatioX: Math.abs(dx/width), swipeRatioY: Math.abs(dy/height)};
const angle = Math.abs(360*(Math.atan(-dy/dx)/6.284));
this.resetAnimations();
if(angle > 45){
//swipe up or down
//dy > 0, swipe down else swipe up
if ( swipeRatioY > 0.1){
if(dy < 0)
onSwipeUp();
else
onSwipeDown();
}
}else{
//swipe right or left
//dx > 0, swipe right else swipe left.
if(swipeRatioX > 0.1){
if(dx > 0)
onSwipeRight();
else
onSwipeLeft();
}
}
}
resetAnimations = () => {
this.state.moveAnimation.stopAnimation(() => {
this.state.moveAnimation.setValue({x: 0, y: 0});
});
this.state.fadeAnimation.stopAnimation(() => {
this.state.fadeAnimation.setValue(1);
});
}
setDimensions = ({nativeEvent: { layout: { width, height } }}) => {
this.setState({width, height});
}
getContainerStyle = () => {
const { fadeAnimation, moveAnimation: { x, y} } = this.state;
const style = {
flex:1,
opacity: fadeAnimation,
transform: [
{ translateX: x },
{ translateY: y }
]
};
return style;
}
render(){
const { children } = this.props;
return (
<Animated.View { ...this._panResponder.panHandlers }
style={this.getContainerStyle()}
onLayout={this.setDimensions}
>
{children}
</Animated.View>
);
}
}
Swiper.PropTypes = {
enableParentScroll: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func
]),
onSwipeUp: PropTypes.func,
onSwipeDown: PropTypes.func,
onSwipeLeft: PropTypes.func,
onSwipeRight: PropTypes.func,
}
Swiper.defaultProps = {
enableParentScroll: false,
onSwipeUp: () => false,
onSwipeDown: () => false,
onSwipeLeft: () => false,
onSwipeRight: () => false,
}