event.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. var Eventful = require("../mixin/Eventful");
  2. exports.Dispatcher = Eventful;
  3. var env = require("./env");
  4. /**
  5. * 事件辅助类
  6. * @module zrender/core/event
  7. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  8. */
  9. var isDomLevel2 = typeof window !== 'undefined' && !!window.addEventListener;
  10. var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
  11. function getBoundingClientRect(el) {
  12. // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect
  13. return el.getBoundingClientRect ? el.getBoundingClientRect() : {
  14. left: 0,
  15. top: 0
  16. };
  17. } // `calculate` is optional, default false
  18. function clientToLocal(el, e, out, calculate) {
  19. out = out || {}; // According to the W3C Working Draft, offsetX and offsetY should be relative
  20. // to the padding edge of the target element. The only browser using this convention
  21. // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does
  22. // not support the properties.
  23. // (see http://www.jacklmoore.com/notes/mouse-position/)
  24. // In zr painter.dom, padding edge equals to border edge.
  25. // FIXME
  26. // When mousemove event triggered on ec tooltip, target is not zr painter.dom, and
  27. // offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y
  28. // is too complex. So css-transfrom dont support in this case temporarily.
  29. if (calculate || !env.canvasSupported) {
  30. defaultGetZrXY(el, e, out);
  31. } // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned
  32. // ancestor element, so we should make sure el is positioned (e.g., not position:static).
  33. // BTW1, Webkit don't return the same results as FF in non-simple cases (like add
  34. // zoom-factor, overflow / opacity layers, transforms ...)
  35. // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.
  36. // <https://bugs.jquery.com/ticket/8523#comment:14>
  37. // BTW3, In ff, offsetX/offsetY is always 0.
  38. else if (env.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) {
  39. out.zrX = e.layerX;
  40. out.zrY = e.layerY;
  41. } // For IE6+, chrome, safari, opera. (When will ff support offsetX?)
  42. else if (e.offsetX != null) {
  43. out.zrX = e.offsetX;
  44. out.zrY = e.offsetY;
  45. } // For some other device, e.g., IOS safari.
  46. else {
  47. defaultGetZrXY(el, e, out);
  48. }
  49. return out;
  50. }
  51. function defaultGetZrXY(el, e, out) {
  52. // This well-known method below does not support css transform.
  53. var box = getBoundingClientRect(el);
  54. out.zrX = e.clientX - box.left;
  55. out.zrY = e.clientY - box.top;
  56. }
  57. /**
  58. * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标.
  59. * `calculate` is optional, default false.
  60. */
  61. function normalizeEvent(el, e, calculate) {
  62. e = e || window.event;
  63. if (e.zrX != null) {
  64. return e;
  65. }
  66. var eventType = e.type;
  67. var isTouch = eventType && eventType.indexOf('touch') >= 0;
  68. if (!isTouch) {
  69. clientToLocal(el, e, e, calculate);
  70. e.zrDelta = e.wheelDelta ? e.wheelDelta / 120 : -(e.detail || 0) / 3;
  71. } else {
  72. var touch = eventType != 'touchend' ? e.targetTouches[0] : e.changedTouches[0];
  73. touch && clientToLocal(el, touch, e, calculate);
  74. } // Add which for click: 1 === left; 2 === middle; 3 === right; otherwise: 0;
  75. // See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js
  76. // If e.which has been defined, if may be readonly,
  77. // see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
  78. var button = e.button;
  79. if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) {
  80. e.which = button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0;
  81. }
  82. return e;
  83. }
  84. function addEventListener(el, name, handler) {
  85. if (isDomLevel2) {
  86. el.addEventListener(name, handler);
  87. } else {
  88. el.attachEvent('on' + name, handler);
  89. }
  90. }
  91. function removeEventListener(el, name, handler) {
  92. if (isDomLevel2) {
  93. el.removeEventListener(name, handler);
  94. } else {
  95. el.detachEvent('on' + name, handler);
  96. }
  97. }
  98. /**
  99. * preventDefault and stopPropagation.
  100. * Notice: do not do that in zrender. Upper application
  101. * do that if necessary.
  102. *
  103. * @memberOf module:zrender/core/event
  104. * @method
  105. * @param {Event} e : event对象
  106. */
  107. var stop = isDomLevel2 ? function (e) {
  108. e.preventDefault();
  109. e.stopPropagation();
  110. e.cancelBubble = true;
  111. } : function (e) {
  112. e.returnValue = false;
  113. e.cancelBubble = true;
  114. };
  115. function notLeftMouse(e) {
  116. // If e.which is undefined, considered as left mouse event.
  117. return e.which > 1;
  118. } // 做向上兼容
  119. exports.clientToLocal = clientToLocal;
  120. exports.normalizeEvent = normalizeEvent;
  121. exports.addEventListener = addEventListener;
  122. exports.removeEventListener = removeEventListener;
  123. exports.stop = stop;
  124. exports.notLeftMouse = notLeftMouse;