1 | import _extends from 'babel-runtime/helpers/extends';
|
2 | import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
|
3 | import _createClass from 'babel-runtime/helpers/createClass';
|
4 | import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
|
5 | import _inherits from 'babel-runtime/helpers/inherits';
|
6 |
|
7 | import React, { Component } from 'react';
|
8 | import { calcRotation, getEventName, now, calcMutliFingerStatus, calcMoveStatus, shouldTriggerSwipe, shouldTriggerDirection, getDirection, getDirectionEventName } from './util';
|
9 | import { PRESS, DIRECTION_ALL, DIRECTION_VERTICAL, DIRECTION_HORIZONTAL } from './config';
|
10 | ;
|
11 | ;
|
12 | var directionMap = {
|
13 | all: DIRECTION_ALL,
|
14 | vertical: DIRECTION_VERTICAL,
|
15 | horizontal: DIRECTION_HORIZONTAL
|
16 | };
|
17 |
|
18 | var Gesture = function (_Component) {
|
19 | _inherits(Gesture, _Component);
|
20 |
|
21 | function Gesture(props) {
|
22 | _classCallCheck(this, Gesture);
|
23 |
|
24 | var _this = _possibleConstructorReturn(this, (Gesture.__proto__ || Object.getPrototypeOf(Gesture)).call(this, props));
|
25 |
|
26 | _this.state = {};
|
27 | _this.triggerEvent = function (name) {
|
28 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
29 | args[_key - 1] = arguments[_key];
|
30 | }
|
31 |
|
32 | var cb = _this.props[name];
|
33 | if (typeof cb === 'function') {
|
34 |
|
35 | cb.apply(undefined, [_this.getGestureState()].concat(args));
|
36 | }
|
37 | };
|
38 | _this.triggerCombineEvent = function (mainEventName, eventStatus) {
|
39 | for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
|
40 | args[_key2 - 2] = arguments[_key2];
|
41 | }
|
42 |
|
43 | _this.triggerEvent.apply(_this, [mainEventName].concat(args));
|
44 | _this.triggerSubEvent.apply(_this, [mainEventName, eventStatus].concat(args));
|
45 | };
|
46 | _this.triggerSubEvent = function (mainEventName, eventStatus) {
|
47 | for (var _len3 = arguments.length, args = Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
|
48 | args[_key3 - 2] = arguments[_key3];
|
49 | }
|
50 |
|
51 | if (eventStatus) {
|
52 | var subEventName = getEventName(mainEventName, eventStatus);
|
53 | _this.triggerEvent.apply(_this, [subEventName].concat(args));
|
54 | }
|
55 | };
|
56 | _this.triggerPinchEvent = function (mainEventName, eventStatus) {
|
57 | for (var _len4 = arguments.length, args = Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
|
58 | args[_key4 - 2] = arguments[_key4];
|
59 | }
|
60 |
|
61 | var scale = _this.gesture.scale;
|
62 |
|
63 | if (eventStatus === 'move' && typeof scale === 'number') {
|
64 | if (scale > 1) {
|
65 | _this.triggerEvent('onPinchOut');
|
66 | }
|
67 | if (scale < 1) {
|
68 | _this.triggerEvent('onPinchIn');
|
69 | }
|
70 | }
|
71 | _this.triggerCombineEvent.apply(_this, [mainEventName, eventStatus].concat(args));
|
72 | };
|
73 | _this.initPressTimer = function () {
|
74 | _this.cleanPressTimer();
|
75 | _this.pressTimer = setTimeout(function () {
|
76 | _this.setGestureState({
|
77 | press: true
|
78 | });
|
79 | _this.triggerEvent('onPress');
|
80 | }, PRESS.time);
|
81 | };
|
82 | _this.cleanPressTimer = function () {
|
83 |
|
84 | _this.pressTimer && clearTimeout(_this.pressTimer);
|
85 | };
|
86 | _this.setGestureState = function (params) {
|
87 | if (!_this.gesture) {
|
88 | _this.gesture = {};
|
89 | }
|
90 | _this.gesture = _extends({}, _this.gesture, params);
|
91 | };
|
92 | _this.getGestureState = function () {
|
93 | if (!_this.gesture) {
|
94 | return _this.gesture;
|
95 | } else {
|
96 |
|
97 | return _extends({}, _this.gesture);
|
98 | }
|
99 | };
|
100 | _this.cleanGestureState = function () {
|
101 | delete _this.gesture;
|
102 | };
|
103 | _this.getTouches = function (e) {
|
104 | return Array.prototype.slice.call(e.touches).map(function (item) {
|
105 | return {
|
106 | x: item.screenX,
|
107 | y: item.screenY
|
108 | };
|
109 | });
|
110 | };
|
111 | _this._handleTouchStart = function (e) {
|
112 | _this.event = e;
|
113 | if (e.touches.length > 1) {
|
114 | e.preventDefault();
|
115 | }
|
116 | _this.initGestureStatus(e);
|
117 | _this.initPressTimer();
|
118 | _this.checkIfMultiTouchStart();
|
119 | };
|
120 | _this.initGestureStatus = function (e) {
|
121 | _this.cleanGestureState();
|
122 |
|
123 | var startTouches = _this.getTouches(e);
|
124 | var startTime = now();
|
125 | var startMutliFingerStatus = calcMutliFingerStatus(startTouches);
|
126 | _this.setGestureState({
|
127 | startTime: startTime,
|
128 | startTouches: startTouches,
|
129 | startMutliFingerStatus: startMutliFingerStatus,
|
130 |
|
131 | time: startTime,
|
132 | touches: startTouches,
|
133 | mutliFingerStatus: startMutliFingerStatus
|
134 | });
|
135 | };
|
136 | _this.checkIfMultiTouchStart = function () {
|
137 | var _this$props = _this.props,
|
138 | enablePinch = _this$props.enablePinch,
|
139 | enableRotate = _this$props.enableRotate;
|
140 | var touches = _this.gesture.touches;
|
141 |
|
142 | if (touches.length > 1 && (enablePinch || enableRotate)) {
|
143 | if (enablePinch) {
|
144 | var startMutliFingerStatus = calcMutliFingerStatus(touches);
|
145 | _this.setGestureState({
|
146 | startMutliFingerStatus: startMutliFingerStatus,
|
147 |
|
148 | pinch: true,
|
149 | scale: 1
|
150 | });
|
151 | _this.triggerCombineEvent('onPinch', 'start');
|
152 | }
|
153 | if (enableRotate) {
|
154 | _this.setGestureState({
|
155 |
|
156 | rotate: true,
|
157 | rotation: 0
|
158 | });
|
159 | _this.triggerCombineEvent('onRotate', 'start');
|
160 | }
|
161 | }
|
162 | };
|
163 | _this._handleTouchMove = function (e) {
|
164 | _this.event = e;
|
165 | if (!_this.gesture) {
|
166 |
|
167 |
|
168 | return;
|
169 | }
|
170 |
|
171 | _this.cleanPressTimer();
|
172 | _this.updateGestureStatus(e);
|
173 | _this.checkIfSingleTouchMove();
|
174 | _this.checkIfMultiTouchMove();
|
175 | };
|
176 | _this.checkIfMultiTouchMove = function () {
|
177 | var _this$gesture = _this.gesture,
|
178 | pinch = _this$gesture.pinch,
|
179 | rotate = _this$gesture.rotate,
|
180 | touches = _this$gesture.touches,
|
181 | startMutliFingerStatus = _this$gesture.startMutliFingerStatus,
|
182 | mutliFingerStatus = _this$gesture.mutliFingerStatus;
|
183 |
|
184 | if (!pinch && !rotate) {
|
185 | return;
|
186 | }
|
187 | if (touches.length < 2) {
|
188 | _this.setGestureState({
|
189 | pinch: false,
|
190 | rotate: false
|
191 | });
|
192 |
|
193 | pinch && _this.triggerCombineEvent('onPinch', 'cancel');
|
194 | rotate && _this.triggerCombineEvent('onRotate', 'cancel');
|
195 | return;
|
196 | }
|
197 | if (pinch) {
|
198 | var scale = mutliFingerStatus.z / startMutliFingerStatus.z;
|
199 | _this.setGestureState({
|
200 | scale: scale
|
201 | });
|
202 | _this.triggerPinchEvent('onPinch', 'move');
|
203 | }
|
204 | if (rotate) {
|
205 | var rotation = calcRotation(startMutliFingerStatus, mutliFingerStatus);
|
206 | _this.setGestureState({
|
207 | rotation: rotation
|
208 | });
|
209 | _this.triggerCombineEvent('onRotate', 'move');
|
210 | }
|
211 | };
|
212 | _this.allowGesture = function () {
|
213 | return shouldTriggerDirection(_this.gesture.direction, _this.directionSetting);
|
214 | };
|
215 | _this.checkIfSingleTouchMove = function () {
|
216 | var _this$gesture2 = _this.gesture,
|
217 | pan = _this$gesture2.pan,
|
218 | touches = _this$gesture2.touches,
|
219 | moveStatus = _this$gesture2.moveStatus;
|
220 |
|
221 | if (touches.length > 1) {
|
222 | _this.setGestureState({
|
223 | pan: false
|
224 | });
|
225 |
|
226 | pan && _this.triggerCombineEvent('onPan', 'cancel');
|
227 | return;
|
228 | }
|
229 | if (moveStatus) {
|
230 | var x = moveStatus.x,
|
231 | y = moveStatus.y;
|
232 |
|
233 | var direction = getDirection(x, y);
|
234 | _this.setGestureState({
|
235 | direction: direction
|
236 | });
|
237 | var eventName = getDirectionEventName(direction);
|
238 | if (!_this.allowGesture()) {
|
239 | return;
|
240 | }
|
241 | if (!pan) {
|
242 | _this.triggerCombineEvent('onPan', 'start');
|
243 | _this.setGestureState({
|
244 | pan: true
|
245 | });
|
246 | } else {
|
247 | _this.triggerCombineEvent('onPan', eventName);
|
248 | _this.triggerSubEvent('onPan', 'move');
|
249 | }
|
250 | }
|
251 | };
|
252 | _this.checkIfMultiTouchEnd = function (status) {
|
253 | var _this$gesture3 = _this.gesture,
|
254 | pinch = _this$gesture3.pinch,
|
255 | rotate = _this$gesture3.rotate;
|
256 |
|
257 | if (pinch) {
|
258 | _this.triggerCombineEvent('onPinch', status);
|
259 | }
|
260 | if (rotate) {
|
261 | _this.triggerCombineEvent('onRotate', status);
|
262 | }
|
263 | };
|
264 | _this.updateGestureStatus = function (e) {
|
265 | var time = now();
|
266 | _this.setGestureState({
|
267 | time: time
|
268 | });
|
269 | if (!e.touches || !e.touches.length) {
|
270 | return;
|
271 | }
|
272 | var _this$gesture4 = _this.gesture,
|
273 | startTime = _this$gesture4.startTime,
|
274 | startTouches = _this$gesture4.startTouches,
|
275 | pinch = _this$gesture4.pinch,
|
276 | rotate = _this$gesture4.rotate;
|
277 |
|
278 | var touches = _this.getTouches(e);
|
279 | var moveStatus = calcMoveStatus(startTouches, touches, time - startTime);
|
280 | var mutliFingerStatus = void 0;
|
281 | if (pinch || rotate) {
|
282 | mutliFingerStatus = calcMutliFingerStatus(touches);
|
283 | }
|
284 | _this.setGestureState({
|
285 |
|
286 | touches: touches,
|
287 | mutliFingerStatus: mutliFingerStatus,
|
288 |
|
289 | moveStatus: moveStatus
|
290 | });
|
291 | };
|
292 | _this._handleTouchEnd = function (e) {
|
293 | _this.event = e;
|
294 | if (!_this.gesture) {
|
295 | return;
|
296 | }
|
297 | _this.cleanPressTimer();
|
298 | _this.updateGestureStatus(e);
|
299 | _this.doSingleTouchEnd('end');
|
300 | _this.checkIfMultiTouchEnd('end');
|
301 | };
|
302 | _this._handleTouchCancel = function (e) {
|
303 | _this.event = e;
|
304 |
|
305 | if (!_this.gesture) {
|
306 | return;
|
307 | }
|
308 | _this.cleanPressTimer();
|
309 | _this.updateGestureStatus(e);
|
310 | _this.doSingleTouchEnd('cancel');
|
311 | _this.checkIfMultiTouchEnd('cancel');
|
312 | };
|
313 | _this.doSingleTouchEnd = function (status) {
|
314 | var _this$gesture5 = _this.gesture,
|
315 | moveStatus = _this$gesture5.moveStatus,
|
316 | pinch = _this$gesture5.pinch,
|
317 | rotate = _this$gesture5.rotate,
|
318 | press = _this$gesture5.press,
|
319 | pan = _this$gesture5.pan,
|
320 | direction = _this$gesture5.direction;
|
321 |
|
322 | if (pinch || rotate || !_this.allowGesture()) {
|
323 | return;
|
324 | }
|
325 | if (moveStatus) {
|
326 | var z = moveStatus.z,
|
327 | velocity = moveStatus.velocity;
|
328 |
|
329 | var swipe = shouldTriggerSwipe(z, velocity);
|
330 | _this.setGestureState({
|
331 | swipe: swipe
|
332 | });
|
333 | if (pan) {
|
334 | _this.triggerCombineEvent('onPan', status);
|
335 | }
|
336 | if (swipe) {
|
337 | var directionEvName = getDirectionEventName(direction);
|
338 | _this.triggerCombineEvent('onSwipe', directionEvName);
|
339 | return;
|
340 | }
|
341 | }
|
342 | if (press) {
|
343 | _this.triggerEvent('onPressUp');
|
344 | return;
|
345 | }
|
346 | _this.triggerEvent('onTap');
|
347 | };
|
348 | _this.getTouchAction = function () {
|
349 | var _this$props2 = _this.props,
|
350 | enablePinch = _this$props2.enablePinch,
|
351 | enableRotate = _this$props2.enableRotate;
|
352 | var directionSetting = _this.directionSetting;
|
353 |
|
354 | if (enablePinch || enableRotate || directionSetting === DIRECTION_ALL) {
|
355 | return 'pan-x pan-y';
|
356 | }
|
357 | if (directionSetting === DIRECTION_VERTICAL) {
|
358 | return 'pan-x';
|
359 | }
|
360 | if (directionSetting === DIRECTION_HORIZONTAL) {
|
361 | return 'pan-y';
|
362 | }
|
363 | return 'auto';
|
364 | };
|
365 | _this.directionSetting = directionMap[props.direction];
|
366 | return _this;
|
367 | }
|
368 |
|
369 | _createClass(Gesture, [{
|
370 | key: 'componentWillUnmount',
|
371 | value: function componentWillUnmount() {
|
372 | this.cleanPressTimer();
|
373 | }
|
374 | }, {
|
375 | key: 'render',
|
376 | value: function render() {
|
377 | var children = this.props.children;
|
378 |
|
379 | var child = React.Children.only(children);
|
380 | var touchAction = this.getTouchAction();
|
381 | var events = {
|
382 | onTouchStart: this._handleTouchStart,
|
383 | onTouchMove: this._handleTouchMove,
|
384 | onTouchCancel: this._handleTouchCancel,
|
385 | onTouchEnd: this._handleTouchEnd
|
386 | };
|
387 | return React.cloneElement(child, _extends({}, events, { style: {
|
388 | touchAction: touchAction
|
389 | } }));
|
390 | }
|
391 | }]);
|
392 |
|
393 | return Gesture;
|
394 | }(Component);
|
395 |
|
396 | export default Gesture;
|
397 |
|
398 | Gesture.defaultProps = {
|
399 | enableRotate: false,
|
400 | enablePinch: false,
|
401 | direction: 'all'
|
402 | }; |
\ | No newline at end of file |