eventEmitterMixin.js 6.6 KB

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