vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

460 lines
13 KiB

  1. /**
  2. * Created by Alex on 2/27/2015.
  3. *
  4. */
  5. import {SelectionHandler} from "./components/SelectionHandler"
  6. var util = require('../../util');
  7. class TouchEventHandler {
  8. constructor(body) {
  9. this.body = body;
  10. this.body.eventListeners.onTap = this.onTap.bind(this);
  11. this.body.eventListeners.onTouch = this.onTouch.bind(this);
  12. this.body.eventListeners.onDoubleTap = this.onDoubleTap.bind(this);
  13. this.body.eventListeners.onHold = this.onHold.bind(this);
  14. this.body.eventListeners.onDragStart = this.onDragStart.bind(this);
  15. this.body.eventListeners.onDrag = this.onDrag.bind(this);
  16. this.body.eventListeners.onDragEnd = this.onDragEnd.bind(this);
  17. this.body.eventListeners.onMouseWheel = this.onMouseWheel.bind(this);
  18. this.body.eventListeners.onPinch = this.onPinch.bind(this);
  19. this.body.eventListeners.onMouseMove = this.onMouseMove.bind(this);
  20. this.body.eventListeners.onRelease = this.onRelease.bind(this);
  21. this.touchTime = 0;
  22. this.drag = {};
  23. this.pinch = {};
  24. this.pointerPosition = {x:0,y:0};
  25. this.scale = 1.0;
  26. this.body.emitter.on("_setScale", (scale) => this.scale = scale);
  27. this.selectionHandler = new SelectionHandler(body);
  28. }
  29. setCanvas(canvas) {
  30. this.canvas = canvas;
  31. this.selectionHandler.setCanvas(canvas);
  32. }
  33. /**
  34. * Get the pointer location from a touch location
  35. * @param {{pageX: Number, pageY: Number}} touch
  36. * @return {{x: Number, y: Number}} pointer
  37. * @private
  38. */
  39. getPointer(touch) {
  40. return {
  41. x: touch.pageX - util.getAbsoluteLeft(this.canvas.frame.canvas),
  42. y: touch.pageY - util.getAbsoluteTop(this.canvas.frame.canvas)
  43. };
  44. }
  45. /**
  46. * On start of a touch gesture, store the pointer
  47. * @param event
  48. * @private
  49. */
  50. onTouch(event) {
  51. if (new Date().valueOf() - this.touchTime > 100) {
  52. this.drag.pointer = this.getPointer(event.gesture.center);
  53. this.drag.pinched = false;
  54. this.pinch.scale = this.scale;
  55. // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame)
  56. this.touchTime = new Date().valueOf();
  57. }
  58. }
  59. /**
  60. * handle tap/click event: select/unselect a node
  61. * @private
  62. */
  63. onTap(event) {
  64. console.log("tap",event)
  65. var pointer = this.getPointer(event.gesture.center);
  66. this.pointerPosition = pointer;
  67. this.selectionHandler.selectOnPoint(pointer);
  68. }
  69. /**
  70. * handle drag start event
  71. * @private
  72. */
  73. /**
  74. * This function is called by onDragStart.
  75. * It is separated out because we can then overload it for the datamanipulation system.
  76. *
  77. * @private
  78. */
  79. onDragStart(event) {
  80. // in case the touch event was triggered on an external div, do the initial touch now.
  81. //if (this.drag.pointer === undefined) {
  82. // this.onTouch(event);
  83. //}
  84. //
  85. //var node = this._getNodeAt(this.drag.pointer);
  86. //// note: drag.pointer is set in onTouch to get the initial touch location
  87. //
  88. //this.drag.dragging = true;
  89. //this.drag.selection = [];
  90. //this.drag.translation = this._getTranslation();
  91. //this.drag.nodeId = null;
  92. //this.draggingNodes = false;
  93. //
  94. //if (node != null && this.constants.dragNodes == true) {
  95. // this.draggingNodes = true;
  96. // this.drag.nodeId = node.id;
  97. // // select the clicked node if not yet selected
  98. // if (!node.isSelected()) {
  99. // this._selectObject(node, false);
  100. // }
  101. //
  102. // this.emit("dragStart", {nodeIds: this.getSelection().nodes});
  103. //
  104. // // create an array with the selected nodes and their original location and status
  105. // for (var objectId in this.selectionObj.nodes) {
  106. // if (this.selectionObj.nodes.hasOwnProperty(objectId)) {
  107. // var object = this.selectionObj.nodes[objectId];
  108. // var s = {
  109. // id: object.id,
  110. // node: object,
  111. //
  112. // // store original x, y, xFixed and yFixed, make the node temporarily Fixed
  113. // x: object.x,
  114. // y: object.y,
  115. // xFixed: object.xFixed,
  116. // yFixed: object.yFixed
  117. // };
  118. //
  119. // object.xFixed = true;
  120. // object.yFixed = true;
  121. //
  122. // this.drag.selection.push(s);
  123. // }
  124. // }
  125. //}
  126. }
  127. /**
  128. * handle drag event
  129. * @private
  130. */
  131. onDrag(event) {
  132. //if (this.drag.pinched) {
  133. // return;
  134. //}
  135. //
  136. //// remove the focus on node if it is focussed on by the focusOnNode
  137. //this.releaseNode();
  138. //
  139. //var pointer = this.getPointer(event.gesture.center);
  140. //var me = this;
  141. //var drag = this.drag;
  142. //var selection = drag.selection;
  143. //if (selection && selection.length && this.constants.dragNodes == true) {
  144. // // calculate delta's and new location
  145. // var deltaX = pointer.x - drag.pointer.x;
  146. // var deltaY = pointer.y - drag.pointer.y;
  147. //
  148. // // update position of all selected nodes
  149. // selection.forEach(function (s) {
  150. // var node = s.node;
  151. //
  152. // if (!s.xFixed) {
  153. // node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX);
  154. // }
  155. //
  156. // if (!s.yFixed) {
  157. // node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY);
  158. // }
  159. // });
  160. //
  161. //
  162. // // start _animationStep if not yet running
  163. // if (!this.moving) {
  164. // this.moving = true;
  165. // this.start();
  166. // }
  167. //}
  168. //else {
  169. // // move the network
  170. // if (this.constants.dragNetwork == true) {
  171. // // if the drag was not started properly because the click started outside the network div, start it now.
  172. // if (this.drag.pointer === undefined) {
  173. // this._handleDragStart(event);
  174. // return;
  175. // }
  176. // var diffX = pointer.x - this.drag.pointer.x;
  177. // var diffY = pointer.y - this.drag.pointer.y;
  178. //
  179. // this._setTranslation(
  180. // this.drag.translation.x + diffX,
  181. // this.drag.translation.y + diffY
  182. // );
  183. // this._redraw();
  184. // }
  185. //}
  186. }
  187. /**
  188. * handle drag start event
  189. * @private
  190. */
  191. onDragEnd(event) {
  192. //this.drag.dragging = false;
  193. //var selection = this.drag.selection;
  194. //if (selection && selection.length) {
  195. // selection.forEach(function (s) {
  196. // // restore original xFixed and yFixed
  197. // s.node.xFixed = s.xFixed;
  198. // s.node.yFixed = s.yFixed;
  199. // });
  200. // this.moving = true;
  201. // this.start();
  202. //}
  203. //else {
  204. // this._redraw();
  205. //}
  206. //if (this.draggingNodes == false) {
  207. // this.emit("dragEnd", {nodeIds: []});
  208. //}
  209. //else {
  210. // this.emit("dragEnd", {nodeIds: this.getSelection().nodes});
  211. //}
  212. }
  213. /**
  214. * handle doubletap event
  215. * @private
  216. */
  217. onDoubleTap(event) {
  218. //var pointer = this.getPointer(event.gesture.center);
  219. //this._handleDoubleTap(pointer);
  220. }
  221. /**
  222. * handle long tap event: multi select nodes
  223. * @private
  224. */
  225. onHold(event) {
  226. //var pointer = this.getPointer(event.gesture.center);
  227. //this.pointerPosition = pointer;
  228. //this._handleOnHold(pointer);
  229. }
  230. /**
  231. * handle the release of the screen
  232. *
  233. * @private
  234. */
  235. onRelease(event) {
  236. //var pointer = this.getPointer(event.gesture.center);
  237. //this._handleOnRelease(pointer);
  238. }
  239. /**
  240. * Handle pinch event
  241. * @param event
  242. * @private
  243. */
  244. onPinch(event) {
  245. //var pointer = this.getPointer(event.gesture.center);
  246. //
  247. //this.drag.pinched = true;
  248. //if (!('scale' in this.pinch)) {
  249. // this.pinch.scale = 1;
  250. //}
  251. //
  252. //// TODO: enabled moving while pinching?
  253. //var scale = this.pinch.scale * event.gesture.scale;
  254. //this._zoom(scale, pointer)
  255. }
  256. /**
  257. * Zoom the network in or out
  258. * @param {Number} scale a number around 1, and between 0.01 and 10
  259. * @param {{x: Number, y: Number}} pointer Position on screen
  260. * @return {Number} appliedScale scale is limited within the boundaries
  261. * @private
  262. */
  263. _zoom(scale, pointer) {
  264. //if (this.constants.zoomable == true) {
  265. // var scaleOld = this._getScale();
  266. // if (scale < 0.00001) {
  267. // scale = 0.00001;
  268. // }
  269. // if (scale > 10) {
  270. // scale = 10;
  271. // }
  272. //
  273. // var preScaleDragPointer = null;
  274. // if (this.drag !== undefined) {
  275. // if (this.drag.dragging == true) {
  276. // preScaleDragPointer = this.canvas.DOMtoCanvas(this.drag.pointer);
  277. // }
  278. // }
  279. // // + this.canvas.frame.canvas.clientHeight / 2
  280. // var translation = this._getTranslation();
  281. //
  282. // var scaleFrac = scale / scaleOld;
  283. // var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac;
  284. // var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac;
  285. //
  286. // this._setScale(scale);
  287. // this._setTranslation(tx, ty);
  288. //
  289. // if (preScaleDragPointer != null) {
  290. // var postScaleDragPointer = this.canvas.canvasToDOM(preScaleDragPointer);
  291. // this.drag.pointer.x = postScaleDragPointer.x;
  292. // this.drag.pointer.y = postScaleDragPointer.y;
  293. // }
  294. //
  295. // this._redraw();
  296. //
  297. // if (scaleOld < scale) {
  298. // this.emit("zoom", {direction: "+"});
  299. // }
  300. // else {
  301. // this.emit("zoom", {direction: "-"});
  302. // }
  303. //
  304. // return scale;
  305. //}
  306. }
  307. /**
  308. * Event handler for mouse wheel event, used to zoom the timeline
  309. * See http://adomas.org/javascript-mouse-wheel/
  310. * https://github.com/EightMedia/hammer.js/issues/256
  311. * @param {MouseEvent} event
  312. * @private
  313. */
  314. onMouseWheel(event) {
  315. //// retrieve delta
  316. //var delta = 0;
  317. //if (event.wheelDelta) { /* IE/Opera. */
  318. // delta = event.wheelDelta / 120;
  319. //} else if (event.detail) { /* Mozilla case. */
  320. // // In Mozilla, sign of delta is different than in IE.
  321. // // Also, delta is multiple of 3.
  322. // delta = -event.detail / 3;
  323. //}
  324. //
  325. //// If delta is nonzero, handle it.
  326. //// Basically, delta is now positive if wheel was scrolled up,
  327. //// and negative, if wheel was scrolled down.
  328. //if (delta) {
  329. //
  330. // // calculate the new scale
  331. // var scale = this._getScale();
  332. // var zoom = delta / 10;
  333. // if (delta < 0) {
  334. // zoom = zoom / (1 - zoom);
  335. // }
  336. // scale *= (1 + zoom);
  337. //
  338. // // calculate the pointer location
  339. // var gesture = hammerUtil.fakeGesture(this, event);
  340. // var pointer = this.getPointer(gesture.center);
  341. //
  342. // // apply the new scale
  343. // this._zoom(scale, pointer);
  344. //}
  345. //
  346. //// Prevent default actions caused by mouse wheel.
  347. //event.preventDefault();
  348. }
  349. /**
  350. * Mouse move handler for checking whether the title moves over a node with a title.
  351. * @param {Event} event
  352. * @private
  353. */
  354. onMouseMove(event) {
  355. //var gesture = hammerUtil.fakeGesture(this, event);
  356. //var pointer = this.getPointer(gesture.center);
  357. //var popupVisible = false;
  358. //
  359. //// check if the previously selected node is still selected
  360. //if (this.popup !== undefined) {
  361. // if (this.popup.hidden === false) {
  362. // this._checkHidePopup(pointer);
  363. // }
  364. //
  365. // // if the popup was not hidden above
  366. // if (this.popup.hidden === false) {
  367. // popupVisible = true;
  368. // this.popup.setPosition(pointer.x + 3, pointer.y - 5)
  369. // this.popup.show();
  370. // }
  371. //}
  372. //
  373. //// if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over
  374. //if (this.constants.keyboard.bindToWindow == false && this.constants.keyboard.enabled == true) {
  375. // this.canvas.frame.focus();
  376. //}
  377. //
  378. //// start a timeout that will check if the mouse is positioned above an element
  379. //if (popupVisible === false) {
  380. // var me = this;
  381. // var checkShow = function() {
  382. // me._checkShowPopup(pointer);
  383. // };
  384. //
  385. // if (this.popupTimer) {
  386. // clearInterval(this.popupTimer); // stop any running calculationTimer
  387. // }
  388. // if (!this.drag.dragging) {
  389. // this.popupTimer = setTimeout(checkShow, this.constants.tooltip.delay);
  390. // }
  391. //}
  392. //
  393. ///**
  394. // * Adding hover highlights
  395. // */
  396. //if (this.constants.hover == true) {
  397. // // removing all hover highlights
  398. // for (var edgeId in this.hoverObj.edges) {
  399. // if (this.hoverObj.edges.hasOwnProperty(edgeId)) {
  400. // this.hoverObj.edges[edgeId].hover = false;
  401. // delete this.hoverObj.edges[edgeId];
  402. // }
  403. // }
  404. //
  405. // // adding hover highlights
  406. // var obj = this._getNodeAt(pointer);
  407. // if (obj == null) {
  408. // obj = this._getEdgeAt(pointer);
  409. // }
  410. // if (obj != null) {
  411. // this._hoverObject(obj);
  412. // }
  413. //
  414. // // removing all node hover highlights except for the selected one.
  415. // for (var nodeId in this.hoverObj.nodes) {
  416. // if (this.hoverObj.nodes.hasOwnProperty(nodeId)) {
  417. // if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj == null) {
  418. // this._blurObject(this.hoverObj.nodes[nodeId]);
  419. // delete this.hoverObj.nodes[nodeId];
  420. // }
  421. // }
  422. // }
  423. // this.redraw();
  424. //}
  425. }
  426. }
  427. export {TouchEventHandler};