tooltip.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. "use strict";
  2. var __rest = (this && this.__rest) || function (s, e) {
  3. var t = {};
  4. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  5. t[p] = s[p];
  6. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  7. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  8. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  9. t[p[i]] = s[p[i]];
  10. }
  11. return t;
  12. };
  13. Object.defineProperty(exports, "__esModule", { value: true });
  14. exports.Tooltip = exports.tooltip = exports.seriesTooltip = void 0;
  15. const g_1 = require("@antv/g");
  16. const d3_array_1 = require("d3-array");
  17. const util_1 = require("@antv/util");
  18. const gui_1 = require("@antv/gui");
  19. const scale_1 = require("@antv/scale");
  20. const helper_1 = require("../utils/helper");
  21. const coordinate_1 = require("../utils/coordinate");
  22. const vector_1 = require("../utils/vector");
  23. const scale_2 = require("../utils/scale");
  24. const utils_1 = require("./utils");
  25. const event_1 = require("./event");
  26. function getContainer(group, mount) {
  27. if (mount)
  28. return typeof mount === 'string' ? document.querySelector(mount) : mount;
  29. // @ts-ignore
  30. return group.getRootNode().defaultView.getConfig().container;
  31. }
  32. function getBounding(root) {
  33. const bbox = root.getBounds();
  34. const { min: [x1, y1], max: [x2, y2], } = bbox;
  35. return {
  36. x: x1,
  37. y: y1,
  38. width: x2 - x1,
  39. height: y2 - y1,
  40. };
  41. }
  42. function getContainerOffset(container1, container2) {
  43. const r1 = container1.getBoundingClientRect();
  44. const r2 = container2.getBoundingClientRect();
  45. return {
  46. x: r1.x - r2.x,
  47. y: r1.y - r2.y,
  48. };
  49. }
  50. function createTooltip(container, x0, y0, position, enterable, bounding, containerOffset) {
  51. const tooltipElement = new gui_1.Tooltip({
  52. className: 'tooltip',
  53. style: {
  54. x: x0,
  55. y: y0,
  56. container: containerOffset,
  57. data: [],
  58. bounding,
  59. position,
  60. enterable,
  61. title: '',
  62. offset: [10, 10],
  63. template: {
  64. prefixCls: 'g2-',
  65. },
  66. style: {
  67. '.g2-tooltip': {},
  68. '.g2-tooltip-title': {
  69. overflow: 'hidden',
  70. 'white-space': 'nowrap',
  71. 'text-overflow': 'ellipsis',
  72. },
  73. },
  74. },
  75. });
  76. container.appendChild(tooltipElement.HTMLTooltipElement);
  77. return tooltipElement;
  78. }
  79. function showTooltip({ root, data, x, y, render, event, single, position = 'right-bottom', enterable = false, mount, bounding, }) {
  80. // All the views share the same tooltip.
  81. const canvasContainer = root.getRootNode().defaultView.getConfig().container;
  82. const container = single ? getContainer(root, mount) : root;
  83. const b = bounding || getBounding(root);
  84. const containerOffset = getContainerOffset(canvasContainer, container);
  85. const { tooltipElement = createTooltip(container, x, y, position, enterable, b, containerOffset), } = container;
  86. const { items, title = '' } = data;
  87. tooltipElement.update(Object.assign({ x,
  88. y, data: items, title,
  89. position,
  90. enterable }, (render !== undefined && {
  91. content: render(event, { items, title }),
  92. })));
  93. container.tooltipElement = tooltipElement;
  94. }
  95. function hideTooltip({ root, single, emitter, nativeEvent = true, mount }) {
  96. const container = single ? getContainer(root, mount) : root;
  97. const { tooltipElement } = container;
  98. if (tooltipElement) {
  99. tooltipElement.hide();
  100. if (nativeEvent) {
  101. emitter.emit('tooltip:hide', { nativeEvent });
  102. }
  103. }
  104. }
  105. function destroyTooltip(root) {
  106. const { tooltipElement } = root;
  107. if (tooltipElement) {
  108. tooltipElement.destroy();
  109. root.tooltipElement = undefined;
  110. }
  111. }
  112. function showUndefined(item) {
  113. const { value } = item;
  114. return Object.assign(Object.assign({}, item), { value: value === undefined ? 'undefined' : value });
  115. }
  116. function singleItem(element) {
  117. const { __data__: datum } = element;
  118. const { title, items = [] } = datum;
  119. const newItems = items
  120. .filter(helper_1.defined)
  121. .map((_a) => {
  122. var { color = itemColorOf(element) } = _a, item = __rest(_a, ["color"]);
  123. return (Object.assign(Object.assign({}, item), { color }));
  124. })
  125. .map(showUndefined);
  126. return Object.assign(Object.assign({}, (title && { title })), { items: newItems });
  127. }
  128. function groupNameOf(scale, datum) {
  129. const { color: scaleColor, series: scaleSeries } = scale;
  130. const { color, series } = datum;
  131. const invertAble = (scale) => {
  132. return (scale &&
  133. scale.invert &&
  134. !(scale instanceof scale_1.Identity) &&
  135. !(scale instanceof scale_1.Constant));
  136. };
  137. // For non constant color channel.
  138. if (invertAble(scaleSeries))
  139. return scaleSeries.invert(series);
  140. if (series && series !== color)
  141. return series;
  142. if (invertAble(scaleColor)) {
  143. const name = scaleColor.invert(color);
  144. // For threshold scale.
  145. if (Array.isArray(name))
  146. return null;
  147. return name;
  148. }
  149. return null;
  150. }
  151. function itemColorOf(element) {
  152. const fill = element.getAttribute('fill');
  153. const stroke = element.getAttribute('stroke');
  154. const { __data__: datum } = element;
  155. const { color = fill && fill !== 'transparent' ? fill : stroke } = datum;
  156. return color;
  157. }
  158. function unique(items, key = (d) => d) {
  159. const valueName = new Map(items.map((d) => [key(d), d]));
  160. return Array.from(valueName.values());
  161. }
  162. function groupItems(elements, scale, groupName, data = elements.map((d) => d['__data__'])) {
  163. const key = (d) => (d instanceof Date ? +d : d);
  164. const T = unique(data.map((d) => d.title), key).filter(helper_1.defined);
  165. const newItems = data
  166. .flatMap((datum, i) => {
  167. const element = elements[i];
  168. const { items = [], title } = datum;
  169. const definedItems = items.filter(helper_1.defined);
  170. // If there is only one item, use groupName as title by default.
  171. const useGroupName = groupName !== undefined ? groupName : items.length <= 1 ? true : false;
  172. return definedItems.map((_a) => {
  173. var { color = itemColorOf(element), name } = _a, item = __rest(_a, ["color", "name"]);
  174. const name1 = useGroupName
  175. ? groupNameOf(scale, datum) || name
  176. : name || groupNameOf(scale, datum);
  177. return Object.assign(Object.assign({}, item), { color, name: name1 || title });
  178. });
  179. })
  180. .map(showUndefined);
  181. return Object.assign(Object.assign({}, (T.length > 0 && { title: T.join(',') })), { items: unique(newItems, (d) => `(${key(d.name)}, ${key(d.value)}, ${key(d.color)})`) });
  182. }
  183. function updateRuleY(root, points, _a) {
  184. var { height, width, startX, startY, transposed, polar } = _a, rest = __rest(_a, ["height", "width", "startX", "startY", "transposed", "polar"]);
  185. const defaults = Object.assign({ lineWidth: 1, stroke: '#1b1e23', strokeOpacity: 0.5 }, rest);
  186. const Y = points.map((p) => p[1]);
  187. const X = points.map((p) => p[0]);
  188. const y = (0, d3_array_1.mean)(Y);
  189. const x = (0, d3_array_1.mean)(X);
  190. const pointsOf = () => {
  191. if (polar) {
  192. const cx = startX + width / 2;
  193. const cy = startY + height / 2;
  194. const r = Math.min(width, height) / 2;
  195. const a = (0, vector_1.angle)((0, vector_1.sub)([x, y], [cx, cy]));
  196. const x0 = cx + r * Math.cos(a);
  197. const y0 = cy + r * Math.sin(a);
  198. return [cx, x0, cy, y0];
  199. }
  200. if (transposed) {
  201. return [startX, startX + width, y + startY, y + startY];
  202. }
  203. return [x + startX, x + startX, startY, startY + height];
  204. };
  205. const [x1, x2, y1, y2] = pointsOf();
  206. const createLine = () => {
  207. const line = new g_1.Line({
  208. style: Object.assign({ x1,
  209. x2,
  210. y1,
  211. y2 }, defaults),
  212. });
  213. root.appendChild(line);
  214. return line;
  215. };
  216. const ruleY = root.ruleY || createLine();
  217. ruleY.style.x1 = x1;
  218. ruleY.style.x2 = x2;
  219. ruleY.style.y1 = y1;
  220. ruleY.style.y2 = y2;
  221. root.ruleY = ruleY;
  222. }
  223. function hideRuleY(root) {
  224. if (root.ruleY) {
  225. root.ruleY.remove();
  226. root.ruleY = undefined;
  227. }
  228. }
  229. function interactionKeyof(markState, key) {
  230. return Array.from(markState.values()).some(
  231. // @ts-ignore
  232. (d) => { var _a; return (_a = d.interaction) === null || _a === void 0 ? void 0 : _a[key]; });
  233. }
  234. function maybeValue(specified, defaults) {
  235. return specified === undefined ? defaults : specified;
  236. }
  237. function isEmptyTooltipData(data) {
  238. const { title, items } = data;
  239. if (items.length === 0 && title === undefined)
  240. return true;
  241. return false;
  242. }
  243. function hasSeries(markState) {
  244. return Array.from(markState.values()).some(
  245. // @ts-ignore
  246. (d) => { var _a; return ((_a = d.interaction) === null || _a === void 0 ? void 0 : _a.seriesTooltip) && d.tooltip; });
  247. }
  248. /**
  249. * Show tooltip for series item.
  250. */
  251. function seriesTooltip(root, _a) {
  252. var { elements: elementsof, sort: sortFunction, filter: filterFunction, scale, coordinate, crosshairs, render, groupName, emitter, wait = 50, leading = true, trailing = false, startX = 0, startY = 0, body = true, single = true, position, enterable, mount, bounding, style: _style = {} } = _a, rest = __rest(_a, ["elements", "sort", "filter", "scale", "coordinate", "crosshairs", "render", "groupName", "emitter", "wait", "leading", "trailing", "startX", "startY", "body", "single", "position", "enterable", "mount", "bounding", "style"]);
  253. const elements = elementsof(root);
  254. const transposed = (0, coordinate_1.isTranspose)(coordinate);
  255. const polar = (0, coordinate_1.isPolar)(coordinate);
  256. const style = (0, util_1.deepMix)(_style, rest);
  257. const { innerWidth: width, innerHeight: height } = coordinate.getOptions();
  258. // Split elements into series elements and item elements.
  259. const seriesElements = [];
  260. const itemElements = [];
  261. for (const element of elements) {
  262. const { __data__: data } = element;
  263. const { seriesX } = data;
  264. if (seriesX)
  265. seriesElements.push(element);
  266. else
  267. itemElements.push(element);
  268. }
  269. // Sorted elements from top to bottom visually,
  270. // or from right to left in transpose coordinate.
  271. seriesElements.sort((a, b) => {
  272. const index = transposed ? 0 : 1;
  273. const minY = (d) => d.getBounds().min[index];
  274. return transposed ? minY(b) - minY(a) : minY(a) - minY(b);
  275. });
  276. // Get sortedIndex and X for each series elements
  277. const elementSortedX = new Map(seriesElements.map((element) => {
  278. const { __data__: data } = element;
  279. const { seriesX } = data;
  280. const seriesIndex = seriesX.map((_, i) => i);
  281. const sortedIndex = (0, d3_array_1.sort)(seriesIndex, (i) => seriesX[+i]);
  282. return [element, [sortedIndex, seriesX]];
  283. }));
  284. const ruleStyle = (0, helper_1.subObject)(style, 'crosshairs');
  285. const { x: scaleX } = scale;
  286. // Apply offset for band scale x.
  287. const offsetX = (scaleX === null || scaleX === void 0 ? void 0 : scaleX.getBandWidth) ? scaleX.getBandWidth() / 2 : 0;
  288. const abstractX = (focus) => {
  289. const [normalizedX] = coordinate.invert(focus);
  290. return normalizedX - offsetX;
  291. };
  292. const indexByFocus = (focus, I, X) => {
  293. const finalX = abstractX(focus);
  294. const [minX, maxX] = (0, d3_array_1.sort)([X[0], X[X.length - 1]]);
  295. // Skip x out of range.
  296. if (finalX < minX || finalX > maxX)
  297. return null;
  298. const search = (0, d3_array_1.bisector)((i) => X[+i]).center;
  299. const i = search(I, finalX);
  300. return I[i];
  301. };
  302. const elementsByFocus = (focus, elements) => {
  303. const index = transposed ? 1 : 0;
  304. const x = focus[index];
  305. const extent = (d) => {
  306. const { min, max } = d.getLocalBounds();
  307. return (0, d3_array_1.sort)([min[index], max[index]]);
  308. };
  309. return elements.filter((element) => {
  310. const [min, max] = extent(element);
  311. return x >= min && x <= max;
  312. });
  313. };
  314. const seriesData = (element, index) => {
  315. const { __data__: data } = element;
  316. return Object.fromEntries(Object.entries(data)
  317. .filter(([key]) => key.startsWith('series') && key !== 'series')
  318. .map(([key, V]) => {
  319. const d = V[index];
  320. return [(0, util_1.lowerFirst)(key.replace('series', '')), d];
  321. }));
  322. };
  323. const update = (0, util_1.throttle)((event) => {
  324. const mouse = (0, utils_1.mousePosition)(root, event);
  325. if (!mouse)
  326. return;
  327. const bbox = root.getRenderBounds();
  328. const x = bbox.min[0];
  329. const y = bbox.min[1];
  330. const focus = [mouse[0] - startX, mouse[1] - startY];
  331. if (!focus)
  332. return;
  333. // Get selected item element.
  334. const selectedItems = elementsByFocus(focus, itemElements);
  335. // Get selected data item from both series element and item element.
  336. const selectedSeriesElements = [];
  337. const selectedSeriesData = [];
  338. for (const element of seriesElements) {
  339. const [sortedIndex, X] = elementSortedX.get(element);
  340. const index = indexByFocus(focus, sortedIndex, X);
  341. if (index !== null) {
  342. selectedSeriesElements.push(element);
  343. const d = seriesData(element, index);
  344. const { x, y } = d;
  345. const p = coordinate.map([(x || 0) + offsetX, y || 0]);
  346. selectedSeriesData.push([d, p]);
  347. }
  348. }
  349. // Filter selectedSeriesData with different x,
  350. // make sure there is only one x closest to focusX.
  351. const SX = Array.from(new Set(selectedSeriesData.map((d) => d[0].x)));
  352. const closestX = SX[(0, d3_array_1.minIndex)(SX, (x) => Math.abs(x - abstractX(focus)))];
  353. const filteredSeriesData = selectedSeriesData.filter((d) => d[0].x === closestX);
  354. const selectedData = [
  355. ...filteredSeriesData.map((d) => d[0]),
  356. ...selectedItems.map((d) => d.__data__),
  357. ];
  358. // Get the displayed tooltip data.
  359. const selectedElements = [...selectedSeriesElements, ...selectedItems];
  360. const tooltipData = groupItems(selectedElements, scale, groupName, selectedData);
  361. // Sort items and filter items.
  362. if (sortFunction) {
  363. tooltipData.items.sort((a, b) => sortFunction(a) - sortFunction(b));
  364. }
  365. if (filterFunction) {
  366. tooltipData.items = tooltipData.items.filter(filterFunction);
  367. }
  368. // Hide tooltip with no selected tooltip.
  369. if (selectedElements.length === 0 || isEmptyTooltipData(tooltipData)) {
  370. hide();
  371. return;
  372. }
  373. if (body) {
  374. showTooltip({
  375. root,
  376. data: tooltipData,
  377. x: mouse[0] + x,
  378. y: mouse[1] + y,
  379. render,
  380. event,
  381. single,
  382. position,
  383. enterable,
  384. mount,
  385. bounding,
  386. });
  387. }
  388. if (crosshairs) {
  389. const points = filteredSeriesData.map((d) => d[1]);
  390. updateRuleY(root, points, Object.assign(Object.assign({}, ruleStyle), { width,
  391. height,
  392. startX,
  393. startY,
  394. transposed,
  395. polar }));
  396. }
  397. emitter.emit('tooltip:show', Object.assign(Object.assign({}, event), { nativeEvent: true, data: { data: { x: (0, scale_2.invert)(scale.x, abstractX(focus), true) } } }));
  398. }, wait, { leading, trailing });
  399. const hide = () => {
  400. hideTooltip({ root, single, emitter, mount });
  401. if (crosshairs)
  402. hideRuleY(root);
  403. };
  404. const onTooltipShow = ({ nativeEvent, data }) => {
  405. if (nativeEvent)
  406. return;
  407. const { x } = data.data;
  408. const { x: scaleX } = scale;
  409. const x1 = scaleX.map(x);
  410. const [x2, y2] = coordinate.map([x1, 0.5]);
  411. const { min: [minX, minY], } = root.getRenderBounds();
  412. update({ offsetX: x2 + minX, offsetY: y2 + minY });
  413. };
  414. const onTooltipHide = () => {
  415. hideTooltip({ root, single, emitter, nativeEvent: false, mount });
  416. };
  417. emitter.on('tooltip:show', onTooltipShow);
  418. emitter.on('tooltip:hide', onTooltipHide);
  419. root.addEventListener('pointerenter', update);
  420. root.addEventListener('pointermove', update);
  421. root.addEventListener('pointerleave', hide);
  422. return () => {
  423. root.removeEventListener('pointerenter', update);
  424. root.removeEventListener('pointermove', update);
  425. root.removeEventListener('pointerleave', hide);
  426. emitter.off('tooltip:show', onTooltipShow);
  427. emitter.off('tooltip:hide', onTooltipHide);
  428. destroyTooltip(root);
  429. if (crosshairs)
  430. hideRuleY(root);
  431. };
  432. }
  433. exports.seriesTooltip = seriesTooltip;
  434. /**
  435. * Show tooltip for non-series item.
  436. */
  437. function tooltip(root, { elements: elementsof, scale, render, groupName, sort: sortFunction, filter: filterFunction, emitter, wait = 50, leading = true, trailing = false, groupKey = (d) => d, // group elements by specified key
  438. single = true, position, enterable, datum, view, mount, bounding, }) {
  439. const elements = elementsof(root);
  440. const elementSet = new Set(elements);
  441. const keyGroup = (0, d3_array_1.group)(elements, groupKey);
  442. const pointerover = (0, util_1.throttle)((event) => {
  443. const { target: element } = event;
  444. if (!elementSet.has(element)) {
  445. hideTooltip({ root, single, emitter, mount });
  446. return;
  447. }
  448. const k = groupKey(element);
  449. const group = keyGroup.get(k);
  450. const data = group.length === 1
  451. ? singleItem(group[0])
  452. : groupItems(group, scale, groupName);
  453. // Sort items and sort.
  454. if (sortFunction) {
  455. data.items.sort((a, b) => sortFunction(a) - sortFunction(b));
  456. }
  457. if (filterFunction) {
  458. data.items = data.items.filter(filterFunction);
  459. }
  460. if (isEmptyTooltipData(data)) {
  461. hideTooltip({ root, single, emitter, mount });
  462. return;
  463. }
  464. const { offsetX, offsetY } = event;
  465. showTooltip({
  466. root,
  467. data,
  468. x: offsetX,
  469. y: offsetY,
  470. render,
  471. event,
  472. single,
  473. position,
  474. enterable,
  475. mount,
  476. bounding,
  477. });
  478. emitter.emit('tooltip:show', Object.assign(Object.assign({}, event), { nativeEvent: true, data: {
  479. data: (0, event_1.dataOf)(element, view),
  480. } }));
  481. }, wait, { leading, trailing });
  482. const pointerout = (event) => {
  483. const { target: element } = event;
  484. if (!elementSet.has(element))
  485. return;
  486. hideTooltip({ root, single, emitter, mount });
  487. };
  488. const onTooltipShow = ({ nativeEvent, data }) => {
  489. if (nativeEvent)
  490. return;
  491. const element = (0, utils_1.selectElementByData)(elements, data.data, datum);
  492. if (!element)
  493. return;
  494. const bbox = element.getBBox();
  495. const { x, y, width, height } = bbox;
  496. pointerover({
  497. target: element,
  498. offsetX: x + width / 2,
  499. offsetY: y + height / 2,
  500. });
  501. };
  502. const onTooltipHide = ({ nativeEvent } = {}) => {
  503. if (nativeEvent)
  504. return;
  505. hideTooltip({ root, single, emitter, nativeEvent: false, mount });
  506. };
  507. emitter.on('tooltip:show', onTooltipShow);
  508. emitter.on('tooltip:hide', onTooltipHide);
  509. root.addEventListener('pointerover', pointerover);
  510. root.addEventListener('pointermove', pointerover);
  511. root.addEventListener('pointerout', pointerout);
  512. return () => {
  513. root.removeEventListener('pointerover', pointerover);
  514. root.removeEventListener('pointermove', pointerover);
  515. root.removeEventListener('pointerout', pointerout);
  516. emitter.off('tooltip:show', onTooltipShow);
  517. emitter.off('tooltip:hide', onTooltipHide);
  518. destroyTooltip(root);
  519. };
  520. }
  521. exports.tooltip = tooltip;
  522. function Tooltip(options) {
  523. const { shared, crosshairs, series, name, item = () => ({}), facet = false } = options, rest = __rest(options, ["shared", "crosshairs", "series", "name", "item", "facet"]);
  524. return (target, viewInstances, emitter) => {
  525. const { container, view } = target;
  526. const { scale, markState, coordinate } = view;
  527. // Get default value from mark states.
  528. const defaultSeries = interactionKeyof(markState, 'seriesTooltip');
  529. const defaultShowCrosshairs = interactionKeyof(markState, 'crosshairs');
  530. const plotArea = (0, utils_1.selectPlotArea)(container);
  531. const isSeries = maybeValue(series, defaultSeries);
  532. // For non-facet and series tooltip.
  533. if (isSeries && hasSeries(markState) && !facet) {
  534. return seriesTooltip(plotArea, Object.assign(Object.assign({}, rest), { elements: utils_1.selectG2Elements, scale,
  535. coordinate, crosshairs: maybeValue(crosshairs, defaultShowCrosshairs), item,
  536. emitter }));
  537. }
  538. // For facet and series tooltip.
  539. if (isSeries && facet) {
  540. // Get sub view instances for this view.
  541. const facetInstances = viewInstances.filter((d) => d !== target && d.options.parentKey === target.options.key);
  542. const elements = (0, utils_1.selectFacetG2Elements)(target, viewInstances);
  543. // Use the scale of the first view.
  544. const scale = facetInstances[0].view.scale;
  545. const bbox = plotArea.getBounds();
  546. const startX = bbox.min[0];
  547. const startY = bbox.min[1];
  548. // @todo Nested structure rather than flat structure for facet?
  549. // Add listener to the root area.
  550. // @ts-ignore
  551. return seriesTooltip(plotArea.parentNode.parentNode, Object.assign(Object.assign({}, rest), { elements: () => elements, scale,
  552. coordinate, crosshairs: maybeValue(crosshairs, defaultShowCrosshairs), item,
  553. startX,
  554. startY,
  555. emitter }));
  556. }
  557. return tooltip(plotArea, Object.assign(Object.assign({}, rest), { datum: (0, utils_1.createDatumof)(view), elements: utils_1.selectG2Elements, scale,
  558. coordinate, groupKey: shared ? (0, utils_1.createXKey)(view) : undefined, item,
  559. emitter,
  560. view }));
  561. };
  562. }
  563. exports.Tooltip = Tooltip;
  564. //# sourceMappingURL=tooltip.js.map