UNPKG

@alicloud/cloud-charts

Version:

![](https://img.shields.io/npm/v/@alicloud/cloud-charts?color=%23ff8200)

290 lines (246 loc) 12.2 kB
'use strict'; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports["default"] = _default; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _common = require("./common"); var _reactDom = require("react-dom"); var _themes = _interopRequireDefault(require("../themes")); var _util = require("@antv/util"); // import TooltipController from '@antv/g2/esm/chart/controller/tooltip'; // import { registerComponentController } from '@antv/g2/esm/chart/controller'; // // 自定义 TooltipController 来处理 titleFormatter 的问题 // class WidgetsTooltipController extends TooltipController { // getTooltipItems(point: Types.Point) { // const rawItems = super.getTooltipItems(point); // const view = this.view; // const option = view.getOptions().tooltip; // // @ts-ignore // if (rawItems.length > 0 && typeof option !== 'boolean' && option.customTitle) { // // @ts-ignore // rawItems[0].title = option.customTitle(rawItems[0].title || rawItems[0].name, rawItems); // } // return rawItems; // } // } // registerComponentController('tooltip', WidgetsTooltipController); // 排序函数 var sortFun = { // 升序 asce: function asce(a, b) { return a.value - b.value; }, // 降序 desc: function desc(a, b) { return b.value - a.value; } }; /** * rectTooltip 直角坐标系的tooltip配置 * * @param {this} ctx 组件实例 this 指针 * @param {Chart} chart 图表实例 * @param {Object} config 配置项 * @param {Object} defaultConfig 组件的自定义配置 * @param {Function} onTooltipChange 自定义 tooltip:change 事件 * @param {Object} componentConfig * */ function _default(ctx, chart, config, defaultConfig, onTooltipChange, componentConfig) { if (config.tooltip === false || config.tooltip && typeof config.tooltip !== 'boolean' && config.tooltip.visible === false) { chart.tooltip(false); } else { var _ref = config.tooltip === true ? {} : config.tooltip || {}, sort = _ref.sort, _ref$showTitle = _ref.showTitle, showTitle = _ref$showTitle === void 0 ? true : _ref$showTitle, _ref$showColon = _ref.showColon, showColon = _ref$showColon === void 0 ? false : _ref$showColon, position = _ref.position, offset = _ref.offset, titleFormatter = _ref.titleFormatter, nameFormatter = _ref.nameFormatter, valueFormatter = _ref.valueFormatter, customContent = _ref.customContent, reactContent = _ref.reactContent, customConfig = _ref.customConfig, columns = _ref.columns, lockable = _ref.lockable, dodge = _ref.dodge, customTooltip = _ref.customTooltip; var tooltipConfig = (0, _extends2["default"])({}, defaultConfig, { showTitle: showTitle, // title: '_customTitle_', showCrosshairs: true, // crosshairs 空对象不可省略,否则在混合图表中会没有crosshairs line crosshairs: { type: 'x' }, position: position, offset: offset, shared: true, // inPlot, itemTpl: "<li class=\"g2-tooltip-list-item\" data-index={index}><span class=\"g2-tooltip-marker\" style=\"background:{color}\"></span><span class=\"g2-tooltip-name\">{name}</span>" + (showColon ? ': ' : ' ') + "<span class=\"g2-tooltip-value\">{value}</span></li>", // 尝试自定义title,可以达到效果,但是重绘次数过多,性能差 // customContent(title, data) { // console.log(title, data); // return `<div class="g2-tooltip-title">${title}</div> // <ul class="g2-tooltip-list"> // ${ // data.map((d, i) => { // return `<li class="g2-tooltip-list-item" data-index="${i}"> // <span class="g2-tooltip-marker" style="background:${d.color}"></span> // <span class="g2-tooltip-name">${d.name}</span>:<span class="g2-tooltip-value">${d.value}</span> // </li>`; // }).join('') // } // </ul> // `; // }, customContent: customContent, // @ts-ignore customTooltip: customTooltip }); if (titleFormatter) { // 下面这段是 TooltipCfg.title 不为 function 的逻辑 // tooltipConfig.title = '_customTitle_'; // 下面这段是 TooltipCfg.title 为 function 的逻辑 tooltipConfig.title = function (title, item) { return titleFormatter(title, item); }; // 下面这行是配合自定义 TooltipController // // @ts-ignore // tooltipConfig.customTitle = titleFormatter; } // react tooltip 渲染模式 if (reactContent) { var reactContentDom = document.createElement('div'); reactContentDom.classList.add('g2-tooltip'); reactContentDom.style.width = 'auto'; reactContentDom.style.height = 'auto'; tooltipConfig.customContent = function (title, data) { (0, _reactDom.render)(reactContent(title, data), reactContentDom); return reactContentDom; }; } // 分组不和自定义内容同时使用 if (dodge && !reactContent && !customContent) { var _reactContentDom = document.createElement('div'); _reactContentDom.classList.add('g2-tooltip'); _reactContentDom.style.width = 'auto'; _reactContentDom.style.height = 'auto'; tooltipConfig.customContent = function (name, data) { var title = "<div class=\"g2-tooltip-title\" style=\"margin-top: 12px;margin-bottom: 12px;\">" + name + "</div>"; var listItem = ''; var dodgeGroups = []; data.forEach(function (item) { var _item$mappingData; var rawData = item.data; listItem += "<li class=\"g2-tooltip-list-item\" data-index={index} style=\"margin-bottom:4px;display:flex;align-items: center;\">\n " + ((rawData !== null && rawData !== void 0 && rawData.dodge || rawData !== null && rawData !== void 0 && rawData.facet) && !dodgeGroups.includes((rawData === null || rawData === void 0 ? void 0 : rawData.dodge) || (rawData === null || rawData === void 0 ? void 0 : rawData.facet)) ? "<span style=\"margin-right: 10px;\">" + ((rawData === null || rawData === void 0 ? void 0 : rawData.dodge) || (rawData === null || rawData === void 0 ? void 0 : rawData.facet)) + ": </span>" : "<span style=\"color: rgba(0,0,0,0);margin-right: 10px;\">" + ((rawData === null || rawData === void 0 ? void 0 : rawData.dodge) || (rawData === null || rawData === void 0 ? void 0 : rawData.facet)) + ": </span>") + "\n <span style=\"background-color:" + ((item === null || item === void 0 ? void 0 : (_item$mappingData = item.mappingData) === null || _item$mappingData === void 0 ? void 0 : _item$mappingData.color) || (item === null || item === void 0 ? void 0 : item.color)) + ";\" class=\"g2-tooltip-marker\"></span>\n <span style=\"display:inline-flex;flex:1;justify-content:space-between\">\n <span style=\"margin-right: 16px;\">" + (item === null || item === void 0 ? void 0 : item.name) + ":</span><span>" + (item === null || item === void 0 ? void 0 : item.value) + "</span>\n </span>\n </li>"; dodgeGroups.push((rawData === null || rawData === void 0 ? void 0 : rawData.dodge) || (rawData === null || rawData === void 0 ? void 0 : rawData.facet)); }); _reactContentDom.innerHTML = title + listItem; return _reactContentDom; }; } // 多列设置无法和自定义内容同时使用 if (columns !== false && !reactContent && !customContent) { var tooltipListStyle = {}; if (columns > 1) { tooltipListStyle['column-count'] = columns; } (0, _common.merge)(tooltipConfig, { domStyles: { 'g2-tooltip-list': tooltipListStyle } }); var fontSize1 = _themes["default"]['widgets-font-size-1']; var baseFontSizeNum = (0, _common.pxToNumber)(_themes["default"]['widgets-font-size-1']); // 在 tooltip 展示前,根据 items 个数更新 chart.on('tooltip:show', function (ev) { if (ev.view) { var chartHeight = ev.view.height; // 图表高度最多能容纳的 tooltip 项个数 var maxLen = Math.floor((chartHeight - 3 * baseFontSizeNum) / (2 * baseFontSizeNum)); var _items = ev.data.items; // 计算最终分列数,自动计算最多分 3 列,最少 1 列 var computeColumns = columns || Math.min(3, Math.max(1, Math.ceil(_items.length / maxLen))); var tooltipOptions = ev.view.getOptions().tooltip; tooltipOptions.domStyles['g2-tooltip-list']['column-count'] = computeColumns; if (_items.length % computeColumns !== 0) { tooltipOptions.domStyles['g2-tooltip-list'].margin = "0 0 " + fontSize1 + " 0"; } else { tooltipOptions.domStyles['g2-tooltip-list'].margin = 0; } } }); } if (componentConfig) { Object.assign(tooltipConfig, componentConfig); } if (customConfig) { (0, _common.merge)(tooltipConfig, customConfig); } chart.tooltip(tooltipConfig); if (onTooltipChange) { chart.on('tooltip:change', onTooltipChange); } else { var customValueFormatter = (0, _common.customFormatter)(config.tooltip === true ? {} : config.tooltip || {}); chart.on('tooltip:change', function (ev) { // x: 当前鼠标的 x 坐标, // y: 当前鼠标的 y 坐标, // items: 数组对象,当前 tooltip 显示的每条内容 // title: tooltip 标题 var items = ev.data.items; // console.log(ev); // 如果设置了合法的排序关键字,则开始排序 if (typeof sort === 'function') { items.sort(sort); } else if (sortFun[sort]) { items.sort(sortFun[sort]); } // 格式化标题,下面这段是 TooltipCfg.title 不为 function 的逻辑 // if (titleFormatter && !items[0].data.hasCustomTitle) { // // ev.title = titleFormatter(ev.title, ev.items); // // items[0].title = titleFormatter(items[0].title, items); // items[0].data._customTitle_ = titleFormatter(items[0].data.x, items); // items[0].data.hasCustomTitle = true; // } // console.log(ev); // 对每一项格式化 名字 和 值 items.forEach(function (item, index) { // @ts-ignore var raw = (0, _common.getRawData)(config, ctx.rawData, item); if (valueFormatter) { item.value = valueFormatter(item.value, raw, index, items); } else if (customValueFormatter) { item.value = customValueFormatter(item.value); } if (item.name.startsWith('undefined-name-')) { item.name = ''; } else if (nameFormatter) { item.name = nameFormatter(item.name, raw, index, items); } }); }); } // 支持鼠标单击锁定 if (lockable) { chart.on('plot:click', function () { var isLocked = chart.isTooltipLocked(); if (isLocked) { chart.unlockTooltip(); } else { chart.lockTooltip(); } }); var reflag = false; // 锁定状态下,tooltip 需要额外多一次渲染,避免切换图例显示状态/改变图表尺寸时显示不正确 var rerenderTooltip = (0, _util.debounce)(function () { if (chart.isTooltipLocked()) { if (reflag) { reflag = false; return; } var tooltipController = chart.getController('tooltip'); tooltipController.update(); reflag = true; } }, 100); chart.on('tooltip:show', rerenderTooltip); // 锁定 tooltip 时坐标固定,如果 changeSize,会导致 tooltip 内容发生变化,这里直接解锁 chart.on('beforechangesize', function () { if (chart.isTooltipLocked()) { chart.unlockTooltip().hideTooltip(); } }); } } }