EventEmitterMixin.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* *
  2. *
  3. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4. *
  5. * */
  6. import H from '../../../Core/Globals.js';
  7. import U from '../../../Core/Utilities.js';
  8. var addEvent = U.addEvent, fireEvent = U.fireEvent, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent;
  9. /* eslint-disable valid-jsdoc */
  10. /**
  11. * It provides methods for:
  12. * - adding and handling DOM events and a drag event,
  13. * - mapping a mouse move event to the distance between two following events.
  14. * The units of the distance are specific to a transformation,
  15. * e.g. for rotation they are radians, for scaling they are scale factors.
  16. *
  17. * @private
  18. * @mixin
  19. * @memberOf Annotation
  20. */
  21. var eventEmitterMixin = {
  22. /**
  23. * Add emitter events.
  24. */
  25. addEvents: function () {
  26. var emitter = this, addMouseDownEvent = function (element) {
  27. addEvent(element, H.isTouchDevice ? 'touchstart' : 'mousedown', function (e) {
  28. emitter.onMouseDown(e);
  29. }, { passive: false });
  30. };
  31. addMouseDownEvent(this.graphic.element);
  32. (emitter.labels || []).forEach(function (label) {
  33. if (label.options.useHTML && label.graphic.text) {
  34. // Mousedown event bound to HTML element (#13070).
  35. addMouseDownEvent(label.graphic.text.element);
  36. }
  37. });
  38. objectEach(emitter.options.events, function (event, type) {
  39. var eventHandler = function (e) {
  40. if (type !== 'click' || !emitter.cancelClick) {
  41. event.call(emitter, emitter.chart.pointer.normalize(e), emitter.target);
  42. }
  43. };
  44. if ((emitter.nonDOMEvents || []).indexOf(type) === -1) {
  45. emitter.graphic.on(type, eventHandler);
  46. }
  47. else {
  48. addEvent(emitter, type, eventHandler, { passive: false });
  49. }
  50. });
  51. if (emitter.options.draggable) {
  52. addEvent(emitter, 'drag', emitter.onDrag);
  53. if (!emitter.graphic.renderer.styledMode) {
  54. var cssPointer_1 = {
  55. cursor: {
  56. x: 'ew-resize',
  57. y: 'ns-resize',
  58. xy: 'move'
  59. }[emitter.options.draggable]
  60. };
  61. emitter.graphic.css(cssPointer_1);
  62. (emitter.labels || []).forEach(function (label) {
  63. if (label.options.useHTML && label.graphic.text) {
  64. label.graphic.text.css(cssPointer_1);
  65. }
  66. });
  67. }
  68. }
  69. if (!emitter.isUpdating) {
  70. fireEvent(emitter, 'add');
  71. }
  72. },
  73. /**
  74. * Remove emitter document events.
  75. */
  76. removeDocEvents: function () {
  77. if (this.removeDrag) {
  78. this.removeDrag = this.removeDrag();
  79. }
  80. if (this.removeMouseUp) {
  81. this.removeMouseUp = this.removeMouseUp();
  82. }
  83. },
  84. /**
  85. * Mouse down handler.
  86. */
  87. onMouseDown: function (e) {
  88. var emitter = this, pointer = emitter.chart.pointer, prevChartX, prevChartY;
  89. if (e.preventDefault) {
  90. e.preventDefault();
  91. }
  92. // On right click, do nothing:
  93. if (e.button === 2) {
  94. return;
  95. }
  96. e = pointer.normalize(e);
  97. prevChartX = e.chartX;
  98. prevChartY = e.chartY;
  99. emitter.cancelClick = false;
  100. emitter.chart.hasDraggedAnnotation = true;
  101. emitter.removeDrag = addEvent(H.doc, H.isTouchDevice ? 'touchmove' : 'mousemove', function (e) {
  102. emitter.hasDragged = true;
  103. e = pointer.normalize(e);
  104. e.prevChartX = prevChartX;
  105. e.prevChartY = prevChartY;
  106. fireEvent(emitter, 'drag', e);
  107. prevChartX = e.chartX;
  108. prevChartY = e.chartY;
  109. }, H.isTouchDevice ? { passive: false } : void 0);
  110. emitter.removeMouseUp = addEvent(H.doc, H.isTouchDevice ? 'touchend' : 'mouseup', function (e) {
  111. emitter.cancelClick = emitter.hasDragged;
  112. emitter.hasDragged = false;
  113. emitter.chart.hasDraggedAnnotation = false;
  114. // ControlPoints vs Annotation:
  115. fireEvent(pick(emitter.target, emitter), 'afterUpdate');
  116. emitter.onMouseUp(e);
  117. }, H.isTouchDevice ? { passive: false } : void 0);
  118. },
  119. /**
  120. * Mouse up handler.
  121. */
  122. onMouseUp: function (_e) {
  123. var chart = this.chart, annotation = this.target || this, annotationsOptions = chart.options.annotations, index = chart.annotations.indexOf(annotation);
  124. this.removeDocEvents();
  125. annotationsOptions[index] = annotation.options;
  126. },
  127. /**
  128. * Drag and drop event. All basic annotations should share this
  129. * capability as well as the extended ones.
  130. */
  131. onDrag: function (e) {
  132. if (this.chart.isInsidePlot(e.chartX - this.chart.plotLeft, e.chartY - this.chart.plotTop)) {
  133. var translation = this.mouseMoveToTranslation(e);
  134. if (this.options.draggable === 'x') {
  135. translation.y = 0;
  136. }
  137. if (this.options.draggable === 'y') {
  138. translation.x = 0;
  139. }
  140. if (this.points.length) {
  141. this.translate(translation.x, translation.y);
  142. }
  143. else {
  144. this.shapes.forEach(function (shape) {
  145. shape.translate(translation.x, translation.y);
  146. });
  147. this.labels.forEach(function (label) {
  148. label.translate(translation.x, translation.y);
  149. });
  150. }
  151. this.redraw(false);
  152. }
  153. },
  154. /**
  155. * Map mouse move event to the radians.
  156. */
  157. mouseMoveToRadians: function (e, cx, cy) {
  158. var prevDy = e.prevChartY - cy, prevDx = e.prevChartX - cx, dy = e.chartY - cy, dx = e.chartX - cx, temp;
  159. if (this.chart.inverted) {
  160. temp = prevDx;
  161. prevDx = prevDy;
  162. prevDy = temp;
  163. temp = dx;
  164. dx = dy;
  165. dy = temp;
  166. }
  167. return Math.atan2(dy, dx) - Math.atan2(prevDy, prevDx);
  168. },
  169. /**
  170. * Map mouse move event to the distance between two following events.
  171. */
  172. mouseMoveToTranslation: function (e) {
  173. var dx = e.chartX - e.prevChartX, dy = e.chartY - e.prevChartY, temp;
  174. if (this.chart.inverted) {
  175. temp = dy;
  176. dy = dx;
  177. dx = temp;
  178. }
  179. return {
  180. x: dx,
  181. y: dy
  182. };
  183. },
  184. /**
  185. * Map mouse move to the scale factors.
  186. *
  187. * @param {Object} e event
  188. * @param {number} cx center x
  189. * @param {number} cy center y
  190. **/
  191. mouseMoveToScale: function (e, cx, cy) {
  192. var prevDx = e.prevChartX - cx, prevDy = e.prevChartY - cy, dx = e.chartX - cx, dy = e.chartY - cy, sx = (dx || 1) / (prevDx || 1), sy = (dy || 1) / (prevDy || 1), temp;
  193. if (this.chart.inverted) {
  194. temp = sy;
  195. sy = sx;
  196. sx = temp;
  197. }
  198. return {
  199. x: sx,
  200. y: sy
  201. };
  202. },
  203. /**
  204. * Destroy the event emitter.
  205. */
  206. destroy: function () {
  207. this.removeDocEvents();
  208. removeEvent(this);
  209. this.hcEvents = null;
  210. }
  211. };
  212. export default eventEmitterMixin;