index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import { __assign, __decorate, __extends, __read, __rest, __spreadArray } from "tslib";
  2. import { createDom } from '@antv/dom-util';
  3. import { substitute } from '@antv/util';
  4. import { GUI } from '../../core';
  5. import { applyStyleSheet, throttle } from '../../util';
  6. import { getClassNames, getDefaultTooltipStyle } from './constant';
  7. var Tooltip = /** @class */ (function (_super) {
  8. __extends(Tooltip, _super);
  9. function Tooltip(options) {
  10. var _this = this;
  11. var _a, _b;
  12. var prefixCls = (_b = (_a = options.style) === null || _a === void 0 ? void 0 : _a.template) === null || _b === void 0 ? void 0 : _b.prefixCls;
  13. var CLASS_NAME = getClassNames(prefixCls);
  14. _this = _super.call(this, options, {
  15. data: [],
  16. x: 0,
  17. y: 0,
  18. visibility: 'visible',
  19. title: '',
  20. position: 'bottom-right',
  21. offset: [5, 5],
  22. enterable: false,
  23. container: {
  24. x: 0,
  25. y: 0,
  26. },
  27. bounding: null,
  28. template: {
  29. prefixCls: '',
  30. container: "<div class=\"".concat(CLASS_NAME.CONTAINER, "\"></div>"),
  31. title: "<div class=\"".concat(CLASS_NAME.TITLE, "\"></div>"),
  32. item: "<li class=\"".concat(CLASS_NAME.LIST_ITEM, "\" data-index={index}>\n <span class=\"").concat(CLASS_NAME.NAME, "\">\n <span class=\"").concat(CLASS_NAME.MARKER, "\" style=\"background:{color}\"></span>\n <span class=\"").concat(CLASS_NAME.NAME_LABEL, "\" title=\"{name}\">{name}</span>\n </span>\n <span class=\"").concat(CLASS_NAME.VALUE, "\" title=\"{value}\">{value}</span>\n </li>"),
  33. },
  34. style: getDefaultTooltipStyle(prefixCls),
  35. }) || this;
  36. _this.prevCustomContentKey = _this.attributes.contentKey;
  37. _this.initShape();
  38. _this.render(_this.attributes, _this);
  39. return _this;
  40. }
  41. Object.defineProperty(Tooltip.prototype, "HTMLTooltipElement", {
  42. get: function () {
  43. return this.element;
  44. },
  45. enumerable: false,
  46. configurable: true
  47. });
  48. Tooltip.prototype.getContainer = function () {
  49. return this.element;
  50. };
  51. Object.defineProperty(Tooltip.prototype, "position", {
  52. set: function (_a) {
  53. var _b = __read(_a, 2), x = _b[0], y = _b[1];
  54. this.attributes.x = x;
  55. this.attributes.y = y;
  56. this.updatePosition();
  57. },
  58. enumerable: false,
  59. configurable: true
  60. });
  61. Object.defineProperty(Tooltip.prototype, "elementSize", {
  62. get: function () {
  63. var width = this.element.offsetWidth;
  64. var height = this.element.offsetHeight;
  65. return { width: width, height: height };
  66. },
  67. enumerable: false,
  68. configurable: true
  69. });
  70. Object.defineProperty(Tooltip.prototype, "HTMLTooltipItemsElements", {
  71. get: function () {
  72. var _a = this.attributes, data = _a.data, template = _a.template;
  73. return data.map(function (_a, idx) {
  74. var _b = _a.name, name = _b === void 0 ? '' : _b, _c = _a.color, color = _c === void 0 ? 'black' : _c, index = _a.index, rest = __rest(_a, ["name", "color", "index"]);
  75. var datum = __assign({ name: name, color: color, index: index !== null && index !== void 0 ? index : idx }, rest);
  76. return createDom(substitute(template.item, datum));
  77. });
  78. },
  79. enumerable: false,
  80. configurable: true
  81. });
  82. Tooltip.prototype.render = function (attributes, container) {
  83. this.renderHTMLTooltipElement();
  84. this.updatePosition();
  85. };
  86. Tooltip.prototype.destroy = function () {
  87. var _a;
  88. (_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
  89. _super.prototype.destroy.call(this);
  90. };
  91. /**
  92. * 如果设置了坐标值,显示过程中会立即更新位置并关闭过渡动画
  93. */
  94. Tooltip.prototype.show = function (x, y) {
  95. var _this = this;
  96. var disableTransition = x !== undefined && y !== undefined;
  97. if (disableTransition) {
  98. var transition_1 = this.element.style.transition;
  99. this.element.style.transition = 'none';
  100. this.position = [x !== null && x !== void 0 ? x : +this.attributes.x, y !== null && y !== void 0 ? y : +this.attributes.y];
  101. setTimeout(function () {
  102. _this.element.style.transition = transition_1;
  103. }, 10);
  104. }
  105. this.element.style.visibility = 'visible';
  106. };
  107. Tooltip.prototype.hide = function () {
  108. this.element.style.visibility = 'hidden';
  109. };
  110. /**
  111. * 初始化容器
  112. */
  113. Tooltip.prototype.initShape = function () {
  114. var template = this.attributes.template;
  115. this.element = createDom(template.container);
  116. if (this.id)
  117. this.element.setAttribute('id', this.id);
  118. };
  119. Tooltip.prototype.renderCustomContent = function () {
  120. if (this.prevCustomContentKey !== undefined && this.prevCustomContentKey === this.attributes.contentKey)
  121. return;
  122. this.prevCustomContentKey = this.attributes.contentKey;
  123. var content = this.attributes.content;
  124. if (!content)
  125. return;
  126. if (typeof content === 'string')
  127. this.element.innerHTML = content;
  128. else
  129. this.element.replaceChildren(content);
  130. };
  131. /**
  132. * 更新 HTML 上的内容
  133. */
  134. Tooltip.prototype.renderHTMLTooltipElement = function () {
  135. var _a, _b;
  136. var _c = this.attributes, template = _c.template, title = _c.title, enterable = _c.enterable, style = _c.style, content = _c.content;
  137. var CLASS_NAME = getClassNames(template.prefixCls);
  138. var container = this.element;
  139. this.element.style.pointerEvents = enterable ? 'auto' : 'none';
  140. if (content)
  141. this.renderCustomContent();
  142. else {
  143. if (title) {
  144. container.innerHTML = template.title;
  145. container.getElementsByClassName(CLASS_NAME.TITLE)[0].innerHTML = title;
  146. }
  147. else
  148. (_b = (_a = container.getElementsByClassName(CLASS_NAME.TITLE)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.remove();
  149. var itemsElements = this.HTMLTooltipItemsElements;
  150. var ul = document.createElement('ul');
  151. ul.className = CLASS_NAME.LIST;
  152. ul.replaceChildren.apply(ul, __spreadArray([], __read(itemsElements), false));
  153. var list = this.element.querySelector(".".concat(CLASS_NAME.LIST));
  154. if (list)
  155. list.replaceWith(ul);
  156. else
  157. container.appendChild(ul);
  158. }
  159. applyStyleSheet(container, style);
  160. };
  161. /**
  162. * 根据 position 和指针位置,计算出 tooltip 相对于指针的偏移量
  163. * @param assignPosition {TooltipPosition} tooltip相对于指针的位置,不指定时使用默认参数
  164. */
  165. Tooltip.prototype.getRelativeOffsetFromCursor = function (assignPosition) {
  166. var _a = this.attributes, position = _a.position, offset = _a.offset;
  167. var interPosition = assignPosition || position;
  168. var finalPosition = interPosition.split('-');
  169. var positionScore = { left: [-1, 0], right: [1, 0], top: [0, -1], bottom: [0, 1] };
  170. var _b = this.elementSize, width = _b.width, height = _b.height;
  171. var absolutelyOffset = [-width / 2, -height / 2];
  172. finalPosition.forEach(function (pos) {
  173. var _a = __read(absolutelyOffset, 2), abs1 = _a[0], abs2 = _a[1];
  174. var _b = __read(positionScore[pos], 2), pos1 = _b[0], pos2 = _b[1];
  175. absolutelyOffset = [abs1 + (width / 2 + offset[0]) * pos1, abs2 + (height / 2 + offset[1]) * pos2];
  176. });
  177. return absolutelyOffset;
  178. };
  179. /**
  180. * 将相对于指针的偏移量生效到dom元素上
  181. */
  182. Tooltip.prototype.setOffsetPosition = function (_a) {
  183. var _b = __read(_a, 2), offsetX = _b[0], offsetY = _b[1];
  184. var _c = this.attributes, _d = _c.x, x = _d === void 0 ? 0 : _d, _e = _c.y, y = _e === void 0 ? 0 : _e, _f = _c.container, cx = _f.x, cy = _f.y;
  185. this.element.style.left = "".concat(+x + cx + offsetX, "px");
  186. this.element.style.top = "".concat(+y + cy + offsetY, "px");
  187. };
  188. /**
  189. * 更新tooltip的位置
  190. */
  191. Tooltip.prototype.updatePosition = function () {
  192. // 尝试当前的位置使用默认position能否放下
  193. // 如果不能,则改变取溢出边的反向position
  194. /**
  195. * 默认位置
  196. * ⬇️
  197. * 计算自动调整位置
  198. * ⬇️
  199. * 实际摆放位置
  200. */
  201. this.setOffsetPosition(this.autoPosition(this.getRelativeOffsetFromCursor()));
  202. };
  203. /**
  204. * 计算自动调整位置后的相对位置
  205. * @param offsetX 根据position计算的横向偏移量
  206. * @param offsetY 根据position计算的纵向偏移量
  207. */
  208. Tooltip.prototype.autoPosition = function (_a) {
  209. var _b = __read(_a, 2), offsetX = _b[0], offsetY = _b[1];
  210. var _c = this.attributes, cursorX = _c.x, cursorY = _c.y, bounding = _c.bounding, position = _c.position;
  211. // 如果没有设置 bounds,那么意思就是不限制空间
  212. if (!bounding)
  213. return [offsetX, offsetY];
  214. // 更新前的位置和宽度
  215. var _d = this.element, offsetWidth = _d.offsetWidth, offsetHeight = _d.offsetHeight;
  216. // 预期放置的位置
  217. var _e = __read([+cursorX + offsetX, +cursorY + offsetY], 2), expectLeft = _e[0], expectTop = _e[1];
  218. // 反方向
  219. var inversion = {
  220. left: 'right',
  221. right: 'left',
  222. top: 'bottom',
  223. bottom: 'top',
  224. };
  225. // 各个边界是否超出容器边界
  226. var boundingX = bounding.x, boundingY = bounding.y, boundingWidth = bounding.width, boundingHeight = bounding.height;
  227. var edgeCompare = {
  228. left: expectLeft < boundingX,
  229. right: expectLeft + offsetWidth > boundingX + boundingWidth,
  230. top: expectTop < boundingY,
  231. bottom: expectTop + offsetHeight > boundingY + boundingHeight,
  232. };
  233. // 修正的位置
  234. var correctivePosition = [];
  235. // 判断是否超出边界
  236. position.split('-').forEach(function (pos) {
  237. // 如果在当前方向超出边界,则设置其反方向
  238. if (edgeCompare[pos])
  239. correctivePosition.push(inversion[pos]);
  240. else
  241. correctivePosition.push(pos);
  242. });
  243. var correctedPositionString = correctivePosition.join('-');
  244. return this.getRelativeOffsetFromCursor(correctedPositionString);
  245. };
  246. Tooltip.tag = 'tooltip';
  247. __decorate([
  248. throttle(100, true)
  249. ], Tooltip.prototype, "updatePosition", null);
  250. return Tooltip;
  251. }(GUI));
  252. export { Tooltip };
  253. //# sourceMappingURL=index.js.map