@alicloud/cloud-charts
Version:

332 lines (311 loc) • 17.3 kB
JavaScript
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
import RawTooltipController from '@antv/g2/esm/chart/controller/tooltip';
import ReactDOM from 'react-dom';
import { FullCrossName, HideTooltipEventName } from '../../constants';
import FreeTooltip from '../component/FreeTooltip';
import { PrefixName } from '../../constants';
import React from 'react';
import { getRawData, customFormatter } from '../../common/common';
import "../component/FreeTooltip/index.css";
// @ts-ignore
var WidgetsTooltipController = /*#__PURE__*/function (_RawTooltipController) {
_inheritsLoose(WidgetsTooltipController, _RawTooltipController);
function WidgetsTooltipController(props) {
var _this;
_this = _RawTooltipController.call(this, props) || this;
_this.parentDom = void 0;
_this.tooltipContainer = void 0;
// 锁定tooltip时,图表容器的位置信息
_this.startRect = void 0;
// 锁定tooltip时,tooltip的起始位置
_this.startPosition = void 0;
// 计时器,用于防抖
_this.timer = void 0;
// 监听器,用于监听图表是否可见
_this.observer = void 0;
// 锁定tooltip时监听滚动事件
_this.handleScroll = function () {
if (_this.timer) {
clearTimeout(_this.timer);
_this.timer = null;
}
_this.timer = setTimeout(function () {
// 图表父元素的当前位置
var currentRect = _this.parentDom.getBoundingClientRect();
var offsetX = currentRect.x - _this.startRect.x;
var offsetY = currentRect.y - _this.startRect.y;
// this.tooltipContainer.style.left = `${this.startPosition.x + offsetX}px`;
// this.tooltipContainer.style.top = `${this.startPosition.y + offsetY}px`;
_this.tooltipContainer.style.transform = "translate3d(" + (_this.startPosition.x + offsetX) + "px, " + (_this.startPosition.y + offsetY) + "px, 0px)";
clearTimeout(_this.timer);
_this.timer = null;
}, 50);
};
_this.parentDom = _this.view.getCanvas().get('el').parentNode.parentNode.parentNode;
return _this;
}
var _proto = WidgetsTooltipController.prototype;
_proto.showTooltip = function showTooltip(point) {
var _items,
_this2 = this;
var cfg = this.getTooltipCfg();
var items = this.getTooltipItems(point);
if (cfg !== null && cfg !== void 0 && cfg.customItems) {
items = cfg.customItems(items);
}
if (!((_items = items) !== null && _items !== void 0 && _items.length)) {
return;
}
// 自定义tooltip
if (cfg !== null && cfg !== void 0 && cfg.customTooltip) {
var _widgetsCtx$mergeConf, _this$view, _this$view$widgetsCtx, _config$tooltip, _config$tooltip2, _config$tooltip3, _config$tooltip4, _items2;
// 创建容器
if (!this.tooltipContainer) {
var container = document.createElement('div');
container.className = FullCrossName + " widgets-tooltip";
container.style.cssText = "position: fixed;z-index: 1001; pointer-events: none; top: 0; left: 0;";
document.body.append(container);
this.tooltipContainer = container;
}
this.tooltipContainer.style.visibility = 'visible';
// 图表离开视窗时隐藏tooltip
this.observer = new IntersectionObserver(function (entries) {
for (var _iterator = _createForOfIteratorHelperLoose(entries), _step; !(_step = _iterator()).done;) {
var entry = _step.value;
// 元素离开视口
if (!entry.isIntersecting) {
_this2.unlockTooltip();
_this2.hideTooltip();
}
}
});
this.observer.observe(this.parentDom);
// 通过事件手动隐藏tooltip
window.addEventListener(HideTooltipEventName, function () {
_this2.unlockTooltip();
_this2.hideTooltip();
});
// 绘制
var title = '';
if (cfg !== null && cfg !== void 0 && cfg.showTitle) {
try {
// @ts-ignore
title = this.getTitle(items);
} catch (e) {}
}
// 配置项处理
var config = (_widgetsCtx$mergeConf = this === null || this === void 0 ? void 0 : (_this$view = this.view) === null || _this$view === void 0 ? void 0 : (_this$view$widgetsCtx = _this$view.widgetsCtx) === null || _this$view$widgetsCtx === void 0 ? void 0 : _this$view$widgetsCtx.mergeConfig) !== null && _widgetsCtx$mergeConf !== void 0 ? _widgetsCtx$mergeConf : {};
// 进位相关配置项
var formatConfig;
// 当tooltip中配置了单位相关信息时,直接使用tooltip的配置项,否则使用y轴配置项
if (typeof (config === null || config === void 0 ? void 0 : config.tooltip) === 'object' && (config !== null && config !== void 0 && (_config$tooltip = config.tooltip) !== null && _config$tooltip !== void 0 && _config$tooltip.valueType || config !== null && config !== void 0 && (_config$tooltip2 = config.tooltip) !== null && _config$tooltip2 !== void 0 && _config$tooltip2.unit || config !== null && config !== void 0 && (_config$tooltip3 = config.tooltip) !== null && _config$tooltip3 !== void 0 && _config$tooltip3.needUnitTransform || config !== null && config !== void 0 && (_config$tooltip4 = config.tooltip) !== null && _config$tooltip4 !== void 0 && _config$tooltip4.unitTransformTo)) {
formatConfig = config.tooltip;
} else if (Array.isArray(config.yAxis) && config.yAxis.length >= 2) {
// 双轴
formatConfig = config.yAxis;
} else if (Array.isArray(config.yAxis)) {
var _config$yAxis$, _config$yAxis;
formatConfig = (_config$yAxis$ = config === null || config === void 0 ? void 0 : (_config$yAxis = config.yAxis) === null || _config$yAxis === void 0 ? void 0 : _config$yAxis[0]) !== null && _config$yAxis$ !== void 0 ? _config$yAxis$ : {};
} else {
var _config$yAxis2;
formatConfig = (_config$yAxis2 = config === null || config === void 0 ? void 0 : config.yAxis) !== null && _config$yAxis2 !== void 0 ? _config$yAxis2 : {};
}
// const customValueFormatter = customFormatter(formatConfig);
items.forEach(function (item, index) {
var _this2$view, _this2$view$widgetsCt, _config$tooltip5, _config$tooltip7;
// @ts-ignore
var raw = getRawData(config, _this2 === null || _this2 === void 0 ? void 0 : (_this2$view = _this2.view) === null || _this2$view === void 0 ? void 0 : (_this2$view$widgetsCt = _this2$view.widgetsCtx) === null || _this2$view$widgetsCt === void 0 ? void 0 : _this2$view$widgetsCt.rawData, item);
if (config !== null && config !== void 0 && (_config$tooltip5 = config.tooltip) !== null && _config$tooltip5 !== void 0 && _config$tooltip5.valueFormatter) {
var _config$tooltip6;
item.value = config === null || config === void 0 ? void 0 : (_config$tooltip6 = config.tooltip) === null || _config$tooltip6 === void 0 ? void 0 : _config$tooltip6.valueFormatter(item.value, raw, index, items);
} else {
var customValueFormatter = null;
if (Array.isArray(formatConfig)) {
// 双轴
customValueFormatter = 'y1' in (item === null || item === void 0 ? void 0 : item.data) ? customFormatter(formatConfig[1]) : customFormatter(formatConfig[0]);
} else {
// 单轴
customValueFormatter = customFormatter(formatConfig);
}
if (customValueFormatter) {
item.value = customValueFormatter(item.value);
}
}
if (item.name.startsWith('undefined-name-')) {
item.name = '';
} else if (config !== null && config !== void 0 && (_config$tooltip7 = config.tooltip) !== null && _config$tooltip7 !== void 0 && _config$tooltip7.nameFormatter) {
var _config$tooltip8;
item.name = config === null || config === void 0 ? void 0 : (_config$tooltip8 = config.tooltip) === null || _config$tooltip8 === void 0 ? void 0 : _config$tooltip8.nameFormatter(item.name, raw, index, items);
}
});
var element = cfg.customTooltip === true ? /*#__PURE__*/React.createElement(FreeTooltip, {
title: title,
data: items
}) : cfg.customTooltip(title, items);
ReactDOM.render(element, this.tooltipContainer);
// 计算位置和尺寸
var padding = 10;
var position = {
x: point.x + padding,
y: point.y
};
var parentRect = this.parentDom.getBoundingClientRect();
var bodyWidth = document.body.clientWidth;
var bodyHeight = document.body.clientHeight;
position.x += parentRect.left;
position.y += parentRect.top;
var tooltipRect = this.tooltipContainer.getBoundingClientRect();
// 宽度超过屏幕时
if (position.x + tooltipRect.width > bodyWidth) {
// 判断左边和右边哪边区域更大就放哪边
var leftWidth = position.x - padding;
var rightWidth = bodyWidth - position.x - padding;
if (leftWidth > rightWidth) {
// 移至左侧
position.x = Math.max(position.x - tooltipRect.width - padding, 0);
}
}
// 高度超过屏幕时
if (position.y + tooltipRect.height > bodyHeight) {
// 判断上边和下边哪边区域更大就放哪边
var topHeight = position.y - padding;
var bottomHeight = bodyHeight - position.y - padding;
if (topHeight > bottomHeight) {
// 移至上方
position.y = Math.max(position.y - tooltipRect.height - padding, 0);
}
}
// 定位
// @ts-ignore
this.tooltipContainer.style.transform = "translate3d(" + position.x + "px, " + position.y + "px, 0px)";
if (cfg !== null && cfg !== void 0 && cfg.showMarkers) {
// @ts-ignore
this.renderTooltipMarkers(items, cfg.marker);
}
// 显示辅助线
if (cfg !== null && cfg !== void 0 && cfg.showCrosshairs && (_items2 = items) !== null && _items2 !== void 0 && _items2.length) {
var _items$, _items$2, _cfg$crosshairs;
var dataPoint = {
x: (_items$ = items[0]) === null || _items$ === void 0 ? void 0 : _items$.x,
y: (_items$2 = items[0]) === null || _items$2 === void 0 ? void 0 : _items$2.y
}; // 数据点位置
var isCrosshairsFollowCursor = (cfg === null || cfg === void 0 ? void 0 : (_cfg$crosshairs = cfg.crosshairs) === null || _cfg$crosshairs === void 0 ? void 0 : _cfg$crosshairs.follow) || false;
// @ts-ignore
_RawTooltipController.prototype.renderCrosshairs.call(this, isCrosshairsFollowCursor ? point : dataPoint, cfg);
}
} else {
_RawTooltipController.prototype.showTooltip.call(this, point);
}
// 开启锁定时绘制锁定icon
if (cfg !== null && cfg !== void 0 && cfg.lockable) {
this.drawLockElement(false);
}
};
_proto.hideTooltip = function hideTooltip() {
var cfg = this.getTooltipCfg();
if (cfg !== null && cfg !== void 0 && cfg.customTooltip) {
if (this.tooltipContainer) {
this.tooltipContainer.style.visibility = 'hidden';
}
// @ts-ignore hide the tooltipMarkers
var tooltipMarkersGroup = this.tooltipMarkersGroup;
if (tooltipMarkersGroup) {
tooltipMarkersGroup.hide();
}
// hide crosshairs
// @ts-ignore
var xCrosshair = this.xCrosshair,
yCrosshair = this.yCrosshair;
if (xCrosshair) {
xCrosshair.hide();
}
if (yCrosshair) {
yCrosshair.hide();
}
} else {
_RawTooltipController.prototype.hideTooltip.call(this);
}
};
_proto.destroy = function destroy() {
var cfg = this.getTooltipCfg();
if (cfg !== null && cfg !== void 0 && cfg.customTooltip) {
if (this.tooltipContainer) {
document.body.removeChild(this.tooltipContainer);
this.tooltipContainer = null;
}
// clear crosshairs
// @ts-ignore
var xCrosshair = this.xCrosshair,
yCrosshair = this.yCrosshair;
if (xCrosshair) {
xCrosshair.clear();
}
if (yCrosshair) {
yCrosshair.clear();
}
} else {
_RawTooltipController.prototype.destroy.call(this);
}
};
_proto.lockTooltip = function lockTooltip() {
_RawTooltipController.prototype.lockTooltip.call(this);
if (this.tooltipContainer) {
this.tooltipContainer.style.pointerEvents = 'auto';
}
this.drawLockElement(true);
};
_proto.unlockTooltip = function unlockTooltip() {
var _this3 = this;
_RawTooltipController.prototype.unlockTooltip.call(this);
if (this.tooltipContainer) {
this.tooltipContainer.style.pointerEvents = 'none';
this.observer.disconnect();
window.removeEventListener(HideTooltipEventName, function () {
_this3.unlockTooltip();
_this3.hideTooltip();
});
}
this.drawLockElement(false);
}
// 绘制锁定相关元素
;
_proto.drawLockElement = function drawLockElement(locked) {
var curTooltipContainer = this.tooltipContainer || this.parentDom.querySelector('.g2-tooltip');
if (!curTooltipContainer) {
return;
}
var lockIcon = /*#__PURE__*/React.createElement("svg", {
viewBox: "0 0 1024 1024",
width: "12",
height: "12"
}, /*#__PURE__*/React.createElement("path", {
d: "M921.6 391.68l-288-288c-5.12-5.12-11.52-7.68-17.92-7.68s-13.44 2.56-17.92 7.68L497.28 203.52c-5.12 4.48-7.68 11.52-7.68 17.92s2.56 13.44 7.68 17.92l51.84 51.84-241.28 104.32c-3.2 1.28-5.76 3.2-7.68 5.12L202.88 497.92c-10.24 10.24-10.24 26.24 0 36.48l85.76 85.76-185.6 257.92c-8.96 12.8-7.68 30.08 3.2 40.96 6.4 6.4 14.72 9.6 23.04 9.6 6.4 0 12.8-1.92 18.56-5.76l262.4-181.76 81.28 81.28c10.24 10.24 26.24 10.24 36.48 0l96.64-96.64c1.92-1.92 3.84-4.48 5.12-7.68L737.28 480l48 48c5.12 5.12 11.52 7.68 17.92 7.68s13.44-2.56 17.92-7.68L921.6 427.52c5.12-5.12 7.68-11.52 7.68-17.92s-3.2-13.44-7.68-17.92z"
}));
var unlockIcon = /*#__PURE__*/React.createElement("svg", {
viewBox: "0 0 1024 1024",
width: "12",
height: "12"
}, /*#__PURE__*/React.createElement("path", {
d: "M920.32 391.68l-288-288c-4.48-5.12-10.88-7.68-17.92-7.68s-13.44 2.56-17.92 7.68L496 203.52c-5.12 5.12-7.68 11.52-7.68 17.92s2.56 13.44 7.68 17.92l51.84 51.84-241.28 104.32c-3.2 1.28-5.76 3.2-7.68 5.12L202.24 497.92c-10.24 10.24-10.24 26.24 0 36.48L288 620.16l-185.6 257.92c-8.96 12.8-7.68 30.08 3.2 40.96 6.4 6.4 14.72 9.6 23.04 9.6 6.4 0 12.8-1.92 18.56-5.76l262.4-181.76 81.28 81.28c10.24 10.24 26.24 10.24 36.48 0l96.64-96.64c1.92-1.92 3.84-4.48 5.12-7.68L736 480l48 48c5.12 5.12 11.52 7.68 17.92 7.68s13.44-2.56 17.92-7.68l100.48-100.48c5.12-5.12 7.68-11.52 7.68-17.92s-2.56-13.44-7.68-17.92z m-117.12 63.36l-51.84-51.84c-5.76-5.76-13.44-7.68-21.12-6.4-7.68 1.28-14.08 6.4-17.28 13.44l-135.04 270.08L508.8 748.8l-72.96-72.96c-8.32-8.32-21.12-9.6-30.72-2.56l-239.36 183.68 188.16-234.24c7.04-9.6 5.76-22.4-2.56-30.72l-76.8-76.8 68.48-68.48 273.92-131.2c7.04-3.2 12.16-9.6 14.08-17.28 1.28-7.68-1.28-16-6.4-21.12l-55.68-55.68 45.44-45.44L848 409.6l-44.8 45.44z"
}));
var lockElement = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: PrefixName + "-free-tooltip-lock-icon-background"
}), /*#__PURE__*/React.createElement("div", {
className: PrefixName + "-free-tooltip-lock-icon-container"
}, locked ? lockIcon : unlockIcon));
var lockContainer = curTooltipContainer === null || curTooltipContainer === void 0 ? void 0 : curTooltipContainer.querySelector("." + PrefixName + "-free-tooltip-lock-container");
if (lockContainer) {
ReactDOM.render(lockElement, lockContainer);
} else {
lockContainer = document.createElement('div');
lockContainer.className = PrefixName + "-free-tooltip-lock-container";
ReactDOM.render(lockElement, lockContainer);
curTooltipContainer.appendChild(lockContainer);
}
};
return WidgetsTooltipController;
}(RawTooltipController);
export default WidgetsTooltipController;