NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/g2/esm/util/tooltip.js
2023-09-14 14:47:11 +08:00

325 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { __assign } from "tslib";
import { contains, filter, find, hasKey, isArray, isNil, isNumberEqual, isObject, memoize, values, } from '@antv/util';
import { FIELD_ORIGIN, GROUP_ATTRS } from '../constant';
import { getName } from './scale';
function snapEqual(v1, v2, scale) {
var value1 = scale.translate(v1);
var value2 = scale.translate(v2);
return isNumberEqual(value1, value2);
}
function getXValueByPoint(point, geometry) {
var coordinate = geometry.coordinate;
var xScale = geometry.getXScale();
var range = xScale.range;
var rangeMax = range[range.length - 1];
var rangeMin = range[0];
var invertPoint = coordinate.invert(point);
var xValue = invertPoint.x;
if (coordinate.isPolar && xValue > (1 + rangeMax) / 2) {
xValue = rangeMin; // 极坐标下scale 的 range 被做过特殊处理
}
return xScale.translate(xScale.invert(xValue));
}
function filterYValue(data, point, geometry) {
var coordinate = geometry.coordinate;
var yScale = geometry.getYScale();
var yField = yScale.field;
var invertPoint = coordinate.invert(point);
var yValue = yScale.invert(invertPoint.y);
var result = find(data, function (obj) {
var originData = obj[FIELD_ORIGIN];
return originData[yField][0] <= yValue && originData[yField][1] >= yValue;
});
return result || data[data.length - 1];
}
var getXDistance = memoize(function (scale) {
if (scale.isCategory) {
return 1;
}
var scaleValues = scale.values; // values 是无序的
var length = scaleValues.length;
var min = scale.translate(scaleValues[0]);
var max = min;
for (var index = 0; index < length; index++) {
var value = scaleValues[index];
// 时间类型需要 translate
var numericValue = scale.translate(value);
if (numericValue < min) {
min = numericValue;
}
if (numericValue > max) {
max = numericValue;
}
}
return (max - min) / (length - 1);
});
function getTooltipTitle(originData, geometry, title) {
var titleField = title;
if (!title) {
var positionAttr = geometry.getAttribute('position');
var fields = positionAttr.getFields();
titleField = fields[0];
}
var scales = geometry.scales;
if (scales[titleField]) {
// 如果创建了该字段对应的 scale则通过 scale.getText() 方式取值,因为用户可能对数据进行了格式化
return scales[titleField].getText(originData[titleField]);
}
// 如果没有对应的 scale则从原始数据中取值如果原始数据中仍不存在则直接放回 title 值
return hasKey(originData, titleField) ? originData[titleField] : titleField;
}
function getAttributesForLegend(geometry) {
var attributes = values(geometry.attributes);
return filter(attributes, function (attribute) { return contains(GROUP_ATTRS, attribute.type); });
}
function getTooltipValueScale(geometry) {
var attributes = getAttributesForLegend(geometry);
var scale;
for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
var attribute = attributes_1[_i];
var tmpScale = attribute.getScale(attribute.type);
if (tmpScale && tmpScale.isLinear) {
// 如果指定字段是非 position 的,同时是连续的
scale = tmpScale;
break;
}
}
var xScale = geometry.getXScale();
var yScale = geometry.getYScale();
return scale || yScale || xScale;
}
function getTooltipValue(originData, valueScale) {
var field = valueScale.field;
var value = originData[field];
if (isArray(value)) {
var texts = value.map(function (eachValue) {
return valueScale.getText(eachValue);
});
return texts.join('-');
}
return valueScale.getText(value);
}
// 根据原始数据获取 tooltip item 中 name 值
function getTooltipName(originData, geometry) {
var nameScale;
var groupScales = geometry.getGroupScales();
if (groupScales.length) {
// 如果存在分组类型,取第一个分组类型
nameScale = groupScales[0];
}
if (nameScale) {
var field = nameScale.field;
return nameScale.getText(originData[field]);
}
var valueScale = getTooltipValueScale(geometry);
return getName(valueScale);
}
/**
* @ignore
* Finds data from geometry by point
* @param point canvas point
* @param data an item of geometry.dataArray
* @param geometry
* @returns
*/
export function findDataByPoint(point, data, geometry) {
if (data.length === 0) {
return null;
}
var geometryType = geometry.type;
var xScale = geometry.getXScale();
var yScale = geometry.getYScale();
var xField = xScale.field;
var yField = yScale.field;
var rst = null;
// 热力图采用最小逼近策略查找 point 击中的数据
if (geometryType === 'heatmap' || geometryType === 'point') {
// 将 point 画布坐标转换为原始数据值
var coordinate = geometry.coordinate;
var invertPoint = coordinate.invert(point); // 转换成归一化的数据
var x = xScale.invert(invertPoint.x); // 转换为原始值
var y = yScale.invert(invertPoint.y); // 转换为原始值
var min = Infinity;
for (var index = 0; index < data.length; index++) {
var obj = data[index];
var originData = obj[FIELD_ORIGIN];
var range = Math.pow((originData[xField] - x), 2) + Math.pow((originData[yField] - y), 2);
if (range < min) {
min = range;
rst = obj;
}
}
return rst;
}
// 其他 Geometry 类型按照 x 字段数据进行查找
var first = data[0];
var last = data[data.length - 1];
var xValue = getXValueByPoint(point, geometry);
var firstXValue = first[FIELD_ORIGIN][xField];
var firstYValue = first[FIELD_ORIGIN][yField];
var lastXValue = last[FIELD_ORIGIN][xField];
var isYArray = yScale.isLinear && isArray(firstYValue); // 考虑 x 维度相同y 是数组区间的情况
// 如果 x 的值是数组
if (isArray(firstXValue)) {
for (var index = 0; index < data.length; index++) {
var record = data[index];
var originData = record[FIELD_ORIGIN];
// xValue 在 originData[xField] 的数值区间内
if (xScale.translate(originData[xField][0]) <= xValue && xScale.translate(originData[xField][1]) >= xValue) {
if (isYArray) {
// 层叠直方图场景x 和 y 都是数组区间
if (!isArray(rst)) {
rst = [];
}
rst.push(record);
}
else {
rst = record;
break;
}
}
}
if (isArray(rst)) {
rst = filterYValue(rst, point, geometry);
}
}
else {
var next = void 0;
if (!xScale.isLinear && xScale.type !== 'timeCat') {
// x 轴对应的数据为非线性以及非时间类型的数据采用遍历查找
for (var index = 0; index < data.length; index++) {
var record = data[index];
var originData = record[FIELD_ORIGIN];
if (snapEqual(originData[xField], xValue, xScale)) {
if (isYArray) {
if (!isArray(rst)) {
rst = [];
}
rst.push(record);
}
else {
rst = record;
break;
}
}
else if (xScale.translate(originData[xField]) <= xValue) {
last = record;
next = data[index + 1];
}
}
if (isArray(rst)) {
rst = filterYValue(rst, point, geometry);
}
}
else {
// x 轴对应的数据为线性以及时间类型,进行二分查找,性能更好
if ((xValue > xScale.translate(lastXValue) || xValue < xScale.translate(firstXValue))
&& (xValue > xScale.max || xValue < xScale.min)) {
// 不在数据范围内
return null;
}
var firstIdx = 0;
var lastIdx = data.length - 1;
var middleIdx = void 0;
while (firstIdx <= lastIdx) {
middleIdx = Math.floor((firstIdx + lastIdx) / 2);
var item = data[middleIdx][FIELD_ORIGIN][xField];
if (snapEqual(item, xValue, xScale)) {
return data[middleIdx];
}
if (xScale.translate(item) <= xScale.translate(xValue)) {
firstIdx = middleIdx + 1;
last = data[middleIdx];
next = data[middleIdx + 1];
}
else {
if (lastIdx === 0) {
last = data[0];
}
lastIdx = middleIdx - 1;
}
}
}
if (last && next) {
// 计算最逼近的
if (Math.abs(xScale.translate(last[FIELD_ORIGIN][xField]) - xValue) >
Math.abs(xScale.translate(next[FIELD_ORIGIN][xField]) - xValue)) {
last = next;
}
}
}
var distance = getXDistance(geometry.getXScale()); // 每个分类间的平均间距
if (!rst && Math.abs(xScale.translate(last[FIELD_ORIGIN][xField]) - xValue) <= distance / 2) {
rst = last;
}
return rst;
}
/**
* @ignore
* Gets tooltip items
* @param data
* @param geometry
* @param [title]
* @returns
*/
export function getTooltipItems(data, geometry, title) {
if (title === void 0) { title = ''; }
var originData = data[FIELD_ORIGIN];
var tooltipTitle = getTooltipTitle(originData, geometry, title);
var tooltipOption = geometry.tooltipOption;
var defaultColor = geometry.theme.defaultColor;
var items = [];
var name;
var value;
function addItem(itemName, itemValue) {
if (!isNil(itemValue) && itemValue !== '') {
// 值为 null的时候忽视
var item = {
title: tooltipTitle,
data: originData,
mappingData: data,
name: itemName || tooltipTitle,
value: itemValue,
color: data.color || defaultColor,
marker: true,
};
items.push(item);
}
}
if (isObject(tooltipOption)) {
var fields = tooltipOption.fields, callback = tooltipOption.callback;
if (callback) {
// 用户定义了回调函数
var callbackParams = fields.map(function (field) {
return data[FIELD_ORIGIN][field];
});
var cfg = callback.apply(void 0, callbackParams);
var itemCfg = __assign({ data: data[FIELD_ORIGIN], mappingData: data, title: tooltipTitle, color: data.color || defaultColor, marker: true }, cfg);
items.push(itemCfg);
}
else {
var scales = geometry.scales;
for (var _i = 0, fields_1 = fields; _i < fields_1.length; _i++) {
var field = fields_1[_i];
if (!isNil(originData[field])) {
// 字段数据为null, undefined 时不显示
var scale = scales[field];
name = getName(scale);
value = scale.getText(originData[field]);
addItem(name, value);
}
}
}
}
else {
var valueScale = getTooltipValueScale(geometry);
if (!isNil(originData[valueScale.field])) {
// 字段数据为null ,undefined时不显示
value = getTooltipValue(originData, valueScale);
name = getTooltipName(originData, geometry);
addItem(name, value);
}
}
return items;
}
//# sourceMappingURL=tooltip.js.map