TooltipContent.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. var zrUtil = require("zrender/lib/core/util");
  2. var zrColor = require("zrender/lib/tool/color");
  3. var eventUtil = require("zrender/lib/core/event");
  4. var env = require("zrender/lib/core/env");
  5. var formatUtil = require("../../util/format");
  6. var each = zrUtil.each;
  7. var toCamelCase = formatUtil.toCamelCase;
  8. var vendors = ['', '-webkit-', '-moz-', '-o-'];
  9. var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';
  10. /**
  11. * @param {number} duration
  12. * @return {string}
  13. * @inner
  14. */
  15. function assembleTransition(duration) {
  16. var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)';
  17. var transitionText = 'left ' + duration + 's ' + transitionCurve + ',' + 'top ' + duration + 's ' + transitionCurve;
  18. return zrUtil.map(vendors, function (vendorPrefix) {
  19. return vendorPrefix + 'transition:' + transitionText;
  20. }).join(';');
  21. }
  22. /**
  23. * @param {Object} textStyle
  24. * @return {string}
  25. * @inner
  26. */
  27. function assembleFont(textStyleModel) {
  28. var cssText = [];
  29. var fontSize = textStyleModel.get('fontSize');
  30. var color = textStyleModel.getTextColor();
  31. color && cssText.push('color:' + color);
  32. cssText.push('font:' + textStyleModel.getFont());
  33. fontSize && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
  34. each(['decoration', 'align'], function (name) {
  35. var val = textStyleModel.get(name);
  36. val && cssText.push('text-' + name + ':' + val);
  37. });
  38. return cssText.join(';');
  39. }
  40. /**
  41. * @param {Object} tooltipModel
  42. * @return {string}
  43. * @inner
  44. */
  45. function assembleCssText(tooltipModel) {
  46. var cssText = [];
  47. var transitionDuration = tooltipModel.get('transitionDuration');
  48. var backgroundColor = tooltipModel.get('backgroundColor');
  49. var textStyleModel = tooltipModel.getModel('textStyle');
  50. var padding = tooltipModel.get('padding'); // Animation transition. Do not animate when transitionDuration is 0.
  51. transitionDuration && cssText.push(assembleTransition(transitionDuration));
  52. if (backgroundColor) {
  53. if (env.canvasSupported) {
  54. cssText.push('background-Color:' + backgroundColor);
  55. } else {
  56. // for ie
  57. cssText.push('background-Color:#' + zrColor.toHex(backgroundColor));
  58. cssText.push('filter:alpha(opacity=70)');
  59. }
  60. } // Border style
  61. each(['width', 'color', 'radius'], function (name) {
  62. var borderName = 'border-' + name;
  63. var camelCase = toCamelCase(borderName);
  64. var val = tooltipModel.get(camelCase);
  65. val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px'));
  66. }); // Text style
  67. cssText.push(assembleFont(textStyleModel)); // Padding
  68. if (padding != null) {
  69. cssText.push('padding:' + formatUtil.normalizeCssArray(padding).join('px ') + 'px');
  70. }
  71. return cssText.join(';') + ';';
  72. }
  73. /**
  74. * @alias module:echarts/component/tooltip/TooltipContent
  75. * @constructor
  76. */
  77. function TooltipContent(container, api) {
  78. var el = document.createElement('div');
  79. var zr = this._zr = api.getZr();
  80. this.el = el;
  81. this._x = api.getWidth() / 2;
  82. this._y = api.getHeight() / 2;
  83. container.appendChild(el);
  84. this._container = container;
  85. this._show = false;
  86. /**
  87. * @private
  88. */
  89. this._hideTimeout;
  90. var self = this;
  91. el.onmouseenter = function () {
  92. // clear the timeout in hideLater and keep showing tooltip
  93. if (self._enterable) {
  94. clearTimeout(self._hideTimeout);
  95. self._show = true;
  96. }
  97. self._inContent = true;
  98. };
  99. el.onmousemove = function (e) {
  100. e = e || window.event;
  101. if (!self._enterable) {
  102. // Try trigger zrender event to avoid mouse
  103. // in and out shape too frequently
  104. var handler = zr.handler;
  105. eventUtil.normalizeEvent(container, e, true);
  106. handler.dispatch('mousemove', e);
  107. }
  108. };
  109. el.onmouseleave = function () {
  110. if (self._enterable) {
  111. if (self._show) {
  112. self.hideLater(self._hideDelay);
  113. }
  114. }
  115. self._inContent = false;
  116. };
  117. }
  118. TooltipContent.prototype = {
  119. constructor: TooltipContent,
  120. /**
  121. * @private
  122. * @type {boolean}
  123. */
  124. _enterable: true,
  125. /**
  126. * Update when tooltip is rendered
  127. */
  128. update: function () {
  129. // FIXME
  130. // Move this logic to ec main?
  131. var container = this._container;
  132. var stl = container.currentStyle || document.defaultView.getComputedStyle(container);
  133. var domStyle = container.style;
  134. if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
  135. domStyle.position = 'relative';
  136. } // Hide the tooltip
  137. // PENDING
  138. // this.hide();
  139. },
  140. show: function (tooltipModel) {
  141. clearTimeout(this._hideTimeout);
  142. var el = this.el;
  143. el.style.cssText = gCssText + assembleCssText(tooltipModel) // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
  144. + ';left:' + this._x + 'px;top:' + this._y + 'px;' + (tooltipModel.get('extraCssText') || '');
  145. el.style.display = el.innerHTML ? 'block' : 'none';
  146. this._show = true;
  147. },
  148. setContent: function (content) {
  149. this.el.innerHTML = content == null ? '' : content;
  150. },
  151. setEnterable: function (enterable) {
  152. this._enterable = enterable;
  153. },
  154. getSize: function () {
  155. var el = this.el;
  156. return [el.clientWidth, el.clientHeight];
  157. },
  158. moveTo: function (x, y) {
  159. // xy should be based on canvas root. But tooltipContent is
  160. // the sibling of canvas root. So padding of ec container
  161. // should be considered here.
  162. var zr = this._zr;
  163. var viewportRootOffset;
  164. if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
  165. x += viewportRootOffset.offsetLeft;
  166. y += viewportRootOffset.offsetTop;
  167. }
  168. var style = this.el.style;
  169. style.left = x + 'px';
  170. style.top = y + 'px';
  171. this._x = x;
  172. this._y = y;
  173. },
  174. hide: function () {
  175. this.el.style.display = 'none';
  176. this._show = false;
  177. },
  178. hideLater: function (time) {
  179. if (this._show && !(this._inContent && this._enterable)) {
  180. if (time) {
  181. this._hideDelay = time; // Set show false to avoid invoke hideLater mutiple times
  182. this._show = false;
  183. this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
  184. } else {
  185. this.hide();
  186. }
  187. }
  188. },
  189. isShow: function () {
  190. return this._show;
  191. }
  192. };
  193. var _default = TooltipContent;
  194. module.exports = _default;