UNPKG

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