UNPKG

3.92 kBJavaScriptView Raw
1const React = require('react')
2
3const Swipeable = React.createClass({
4 propTypes: {
5 onSwiped: React.PropTypes.func,
6 onSwiping: React.PropTypes.func,
7 onSwipingUp: React.PropTypes.func,
8 onSwipingRight: React.PropTypes.func,
9 onSwipingDown: React.PropTypes.func,
10 onSwipingLeft: React.PropTypes.func,
11 onSwipedUp: React.PropTypes.func,
12 onSwipedRight: React.PropTypes.func,
13 onSwipedDown: React.PropTypes.func,
14 onSwipedLeft: React.PropTypes.func,
15 flickThreshold: React.PropTypes.number,
16 delta: React.PropTypes.number,
17 preventDefaultTouchmoveEvent: React.PropTypes.bool
18 },
19
20 getInitialState: function () {
21 return {
22 x: null,
23 y: null,
24 swiping: false,
25 start: 0
26 }
27 },
28
29 getDefaultProps: function () {
30 return {
31 flickThreshold: 0.6,
32 delta: 10,
33 preventDefaultTouchmoveEvent: true
34 }
35 },
36
37 calculatePos: function (e) {
38 const x = e.changedTouches[0].clientX
39 const y = e.changedTouches[0].clientY
40
41 const xd = this.state.x - x
42 const yd = this.state.y - y
43
44 const axd = Math.abs(xd)
45 const ayd = Math.abs(yd)
46
47 const time = Date.now() - this.state.start
48 const velocity = Math.sqrt(axd * axd + ayd * ayd) / time
49
50 return {
51 deltaX: xd,
52 deltaY: yd,
53 absX: axd,
54 absY: ayd,
55 velocity: velocity
56 }
57 },
58
59 touchStart: function (e) {
60 if (e.touches.length > 1) {
61 return
62 }
63 this.setState({
64 start: Date.now(),
65 x: e.touches[0].clientX,
66 y: e.touches[0].clientY,
67 swiping: false
68 })
69 },
70
71 touchMove: function (e) {
72 if (!this.state.x || !this.state.y || e.touches.length > 1) {
73 return
74 }
75
76 let cancelPageSwipe = false
77 const pos = this.calculatePos(e)
78
79 if (pos.absX < this.props.delta && pos.absY < this.props.delta) {
80 return
81 }
82
83 if (this.props.onSwiping) {
84 this.props.onSwiping(e, pos.deltaX, pos.deltaY, pos.absX, pos.absY, pos.velocity)
85 }
86
87 if (pos.absX > pos.absY) {
88 if (pos.deltaX > 0) {
89 if (this.props.onSwipingLeft) {
90 this.props.onSwipingLeft(e, pos.absX)
91 cancelPageSwipe = true
92 }
93 } else {
94 if (this.props.onSwipingRight) {
95 this.props.onSwipingRight(e, pos.absX)
96 cancelPageSwipe = true
97 }
98 }
99 } else {
100 if (pos.deltaY > 0) {
101 if (this.props.onSwipingUp) {
102 this.props.onSwipingUp(e, pos.absY)
103 cancelPageSwipe = true
104 }
105 } else {
106 if (this.props.onSwipingDown) {
107 this.props.onSwipingDown(e, pos.absY)
108 cancelPageSwipe = true
109 }
110 }
111 }
112
113 this.setState({ swiping: true })
114
115 if (cancelPageSwipe && this.props.preventDefaultTouchmoveEvent) {
116 e.preventDefault()
117 }
118 },
119
120 touchEnd: function (ev) {
121 if (this.state.swiping) {
122 const pos = this.calculatePos(ev)
123
124 const isFlick = pos.velocity > this.props.flickThreshold
125
126 this.props.onSwiped && this.props.onSwiped(
127 ev,
128 pos.deltaX,
129 pos.deltaY,
130 isFlick
131 )
132
133 if (pos.absX > pos.absY) {
134 if (pos.deltaX > 0) {
135 this.props.onSwipedLeft && this.props.onSwipedLeft(ev, pos.deltaX, isFlick)
136 } else {
137 this.props.onSwipedRight && this.props.onSwipedRight(ev, pos.deltaX, isFlick)
138 }
139 } else {
140 if (pos.deltaY > 0) {
141 this.props.onSwipedUp && this.props.onSwipedUp(ev, pos.deltaY, isFlick)
142 } else {
143 this.props.onSwipedDown && this.props.onSwipedDown(ev, pos.deltaY, isFlick)
144 }
145 }
146 }
147
148 this.setState(this.getInitialState())
149 },
150
151 render: function () {
152 return (
153 <div {...this.props}
154 onTouchStart={this.touchStart}
155 onTouchMove={this.touchMove}
156 onTouchEnd={this.touchEnd} >
157 {this.props.children}
158 </div>
159 )
160 }
161})
162
163module.exports = Swipeable