controller.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  2. import { convertPoints } from '../../util/dom'; // 计算滑动的方向
  3. var calcDirection = function calcDirection(start, end) {
  4. var xDistance = end.x - start.x;
  5. var yDistance = end.y - start.y; // x 的距离大于y 说明是横向,否则就是纵向
  6. if (Math.abs(xDistance) > Math.abs(yDistance)) {
  7. return xDistance > 0 ? 'right' : 'left';
  8. }
  9. return yDistance > 0 ? 'down' : 'up';
  10. }; // 计算2点之间的距离
  11. var calcDistance = function calcDistance(point1, point2) {
  12. var xDistance = Math.abs(point2.x - point1.x);
  13. var yDistance = Math.abs(point2.y - point1.y);
  14. return Math.sqrt(xDistance * xDistance + yDistance * yDistance);
  15. };
  16. var getCenter = function getCenter(point1, point2) {
  17. var x = point1.x + (point2.x - point1.x) / 2;
  18. var y = point1.y + (point2.y - point1.y) / 2;
  19. return {
  20. x,
  21. y
  22. };
  23. };
  24. var PRESS_DELAY = 250;
  25. class EventController {
  26. constructor(_ref) {
  27. var _this = this;
  28. var {
  29. canvas,
  30. el
  31. } = _ref;
  32. _defineProperty(this, "_click", function (ev) {
  33. var points = convertPoints(ev, _this.canvas);
  34. ev.points = points;
  35. _this.emitEvent('click', ev);
  36. });
  37. _defineProperty(this, "_start", function (ev) {
  38. var points = convertPoints(ev, _this.canvas);
  39. if (!points) {
  40. return;
  41. }
  42. ev.points = points;
  43. _this.emitEvent('touchstart', ev); // 防止上次的内容没有清理掉,重新reset下
  44. _this.reset(); // 记录touch start 的时间
  45. _this.startTime = Date.now(); // 记录touch start 的点
  46. _this.startPoints = points;
  47. if (points.length > 1) {
  48. _this.startDistance = calcDistance(points[0], points[1]);
  49. _this.center = getCenter(points[0], points[1]);
  50. } else {
  51. // 如果touchstart后停顿250ms, 则也触发press事件
  52. _this.pressTimeout = setTimeout(function () {
  53. // 这里固定触发press事件
  54. var eventType = 'press';
  55. var direction = 'none';
  56. ev.direction = direction;
  57. _this.emitStart(eventType, ev);
  58. _this.emitEvent(eventType, ev);
  59. _this.eventType = eventType;
  60. _this.direction = direction;
  61. }, PRESS_DELAY);
  62. }
  63. });
  64. _defineProperty(this, "_move", function (ev) {
  65. var points = convertPoints(ev, _this.canvas);
  66. if (!points) return;
  67. _this.clearPressTimeout();
  68. ev.points = points;
  69. _this.emitEvent('touchmove', ev);
  70. var startPoints = _this.startPoints;
  71. if (!startPoints) return; // 多指触控
  72. if (points.length > 1) {
  73. // touchstart的距离
  74. var startDistance = _this.startDistance;
  75. var currentDistance = calcDistance(points[0], points[1]);
  76. ev.zoom = currentDistance / startDistance;
  77. ev.center = _this.center; // 触发缩放事件
  78. _this.emitStart('pinch', ev);
  79. _this.emitEvent('pinch', ev);
  80. } else {
  81. var deltaX = points[0].x - startPoints[0].x;
  82. var deltaY = points[0].y - startPoints[0].y;
  83. var direction = _this.direction || calcDirection(startPoints[0], points[0]);
  84. _this.direction = direction; // 获取press或者pan的事件类型
  85. // press 按住滑动, pan表示平移
  86. // 如果start后立刻move,则触发pan, 如果有停顿,则触发press
  87. var eventType = _this.getEventType(points);
  88. ev.direction = direction;
  89. ev.deltaX = deltaX;
  90. ev.deltaY = deltaY;
  91. _this.emitStart(eventType, ev);
  92. _this.emitEvent(eventType, ev); // 记录最后2次move的时间和坐标,为了给swipe事件用
  93. var prevMoveTime = _this.lastMoveTime;
  94. var now = Date.now(); // 最后2次的时间间隔一定要大于0,否则swipe没发计算
  95. if (now - prevMoveTime > 0) {
  96. _this.prevMoveTime = prevMoveTime;
  97. _this.prevMovePoints = _this.lastMovePoints;
  98. _this.lastMoveTime = now;
  99. _this.lastMovePoints = points;
  100. }
  101. }
  102. });
  103. _defineProperty(this, "_end", function (ev) {
  104. var points = convertPoints(ev, _this.canvas);
  105. ev.points = points;
  106. _this.emitEnd(ev);
  107. _this.emitEvent('touchend', ev); // swipe事件处理, 在touchend之后触发
  108. var lastMoveTime = _this.lastMoveTime;
  109. var now = Date.now(); // 做这个判断是为了最后一次touchmove后到end前,还有一个停顿的过程
  110. // 100 是拍的一个值,理论这个值会很短,一般不卡顿的话在10ms以内
  111. if (now - lastMoveTime < 100) {
  112. var prevMoveTime = _this.prevMoveTime || _this.startTime;
  113. var intervalTime = lastMoveTime - prevMoveTime; // 时间间隔一定要大于0, 否则计算没意义
  114. if (intervalTime > 0) {
  115. var prevMovePoints = _this.prevMovePoints || _this.startPoints;
  116. var lastMovePoints = _this.lastMovePoints; // move速率
  117. var velocity = calcDistance(prevMovePoints[0], lastMovePoints[0]) / intervalTime; // 0.3 是参考hammerjs的设置
  118. if (velocity > 0.3) {
  119. ev.velocity = velocity;
  120. ev.direction = calcDirection(prevMovePoints[0], lastMovePoints[0]);
  121. _this.emitEvent('swipe', ev);
  122. }
  123. }
  124. }
  125. _this.reset();
  126. var touches = ev.touches; // 当多指只释放了1指时也会触发end, 这时重新触发一次start
  127. if (touches && touches.length > 0) {
  128. _this._start(ev);
  129. }
  130. });
  131. _defineProperty(this, "_cancel", function (ev) {
  132. _this.emitEvent('touchcancel', ev);
  133. _this.reset();
  134. });
  135. // canvasEl
  136. this.canvas = canvas;
  137. this.delegateEvent(el); // 用来记录当前触发的事件
  138. this.processEvent = {};
  139. }
  140. delegateEvent(canvasEl) {
  141. // 代理这几个事件
  142. canvasEl.addEventListener('click', this._click);
  143. canvasEl.addEventListener('touchstart', this._start);
  144. canvasEl.addEventListener('touchmove', this._move);
  145. canvasEl.addEventListener('touchend', this._end);
  146. canvasEl.addEventListener('touchcancel', this._cancel);
  147. }
  148. emitEvent(type, ev) {
  149. var canvas = this.canvas;
  150. canvas.emit(type, ev);
  151. }
  152. getEventType(points) {
  153. var {
  154. eventType,
  155. canvas,
  156. startTime,
  157. startPoints
  158. } = this;
  159. if (eventType) {
  160. return eventType;
  161. }
  162. var type;
  163. var panEventListeners = canvas.__events.pan; // 如果没有pan事件的监听,默认都是press
  164. if (!panEventListeners || !panEventListeners.length) {
  165. type = 'press';
  166. } else {
  167. // 如果有pan事件的处理,press则需要停顿250ms, 且移动距离小于10
  168. var now = Date.now();
  169. if (now - startTime > PRESS_DELAY && calcDistance(startPoints[0], points[0]) < 10) {
  170. type = 'press';
  171. } else {
  172. type = 'pan';
  173. }
  174. }
  175. this.eventType = type;
  176. return type;
  177. }
  178. enable(eventType) {
  179. this.processEvent[eventType] = true;
  180. } // 是否进行中的事件
  181. isProcess(eventType) {
  182. return this.processEvent[eventType];
  183. } // 触发start事件
  184. emitStart(type, ev) {
  185. if (this.isProcess(type)) {
  186. return;
  187. }
  188. this.enable(type);
  189. this.emitEvent("".concat(type, "start"), ev);
  190. } // 触发end事件
  191. emitEnd(ev) {
  192. var _this2 = this;
  193. var processEvent = this.processEvent;
  194. Object.keys(processEvent).forEach(function (type) {
  195. _this2.emitEvent("".concat(type, "end"), ev);
  196. delete processEvent[type];
  197. });
  198. }
  199. clearPressTimeout() {
  200. if (this.pressTimeout) {
  201. clearTimeout(this.pressTimeout);
  202. this.pressTimeout = 0;
  203. }
  204. }
  205. reset() {
  206. this.clearPressTimeout();
  207. this.startTime = 0;
  208. this.startPoints = null;
  209. this.startDistance = 0;
  210. this.direction = null;
  211. this.eventType = null;
  212. this.pinch = false;
  213. this.prevMoveTime = 0;
  214. this.prevMovePoints = null;
  215. this.lastMoveTime = 0;
  216. this.lastMovePoints = null;
  217. }
  218. }
  219. export default EventController;