@alicloud/cloud-charts
Version:

290 lines (246 loc) • 12.2 kB
JavaScript
;
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();
}
});
}
}
}